Read-only access to one Zero SR/S motorcycle's console dongle: its archive of ride, charge and timed-wake sessions, the bike's event log, battery and motor readings over time, the raw output of the console's commands, and the dongle's live state when it is on WiFi.
Read-only access to one Zero SR/S motorcycle's console dongle: its archive of ride, charge and timed-wake sessions, the bike's event log, battery and motor readings over time, the raw output of the console's commands, and the dongle's live state when it is on WiFi.
A Zero SR/S motorcycle's console dongle: an archive of every session it captured from the bike's main board (one per wake, ride or charge), and the board's live state. Times are the bike's local time, America/Los_Angeles. sessions() says what happened when, reading_names() what figures exist, series() one over time, events() the bike's own log, search() finds text anywhere.
Discoverability
0 of 6 checks0/100
Client listings and public setup information.
mcp.json on main domain
No matching manifest was found at /mcp.json or /.well-known/mcp.json.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description95/100
Sessions in a range, newest first: one per time the bike's main board woke, for a ride, a charge or a timed wake. Start here to see what happened when and to get the id or name the other tools take. A long session is cut into parts, and b0198-001.2 is its second. Each row gives the session's id, name, board, fw, boot (why the dongle booted), started, ended, lines (how many it captured) and states (the bike's state changes it saw, e.g. STRT>PWSU, RUN>HIB, CHRG>HIB). Rows come as columns plus rows; more: true means rows past limit were left out.
The description explains the capability, when to use it, and what to expect.
Inputs92/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
since
the earliest time to include, in the bike's local time (America/Los_Angeles): a date or date-time such as 2026-09-10T14:30, or an age back from now such as -7d, -12h. Nothing is cut off at the start when left out
Clear enough to supply this argument.
until
the latest time to include, written like since; the range stops just before it. Nothing is cut off at the end when left out
Clear enough to supply this argument.
limit
how many sessions come back at once, newest first; when the answer says more, a narrower range shows the older ones
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"type": "object",
"required": [
"columns",
"rows"
],
"properties": {
"more": {
"type": "boolean",
"description": "true when rows past limit were left out; absent otherwise"
},
"rows": {
"type": "array",
"items": {
"type": "array",
"items": {}
},
"description": "one array per row, its values in this column order: id is the session's id, which other tools take; name is its name, e.g. b0194-001, or b0198-001.2 for a later part of a long session; board is the dongle that captured it; fw is that dongle's firmware version; boot is why the dongle booted, e.g. power-on; started is the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter; ended is the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter; lines is how many lines it captured; states is the bike's state changes it saw, in order, e.g. [\"RUN>HIB\"]"
},
"columns": {
"type": "array",
"items": {
"type": "string"
},
"description": "always id, name, board, fw, boot, started, ended, lines, states"
}
}
}
Original tool metadata
{
"name": "sessions",
"title": "Sessions",
"description": "Sessions in a range, newest first: one per time the bike's main board woke, for a ride, a charge or a timed wake. Start here to see what happened when and to get the id or name the other tools take. A long session is cut into parts, and b0198-001.2 is its second. Each row gives the session's id, name, board, fw, boot (why the dongle booted), started, ended, lines (how many it captured) and states (the bike's state changes it saw, e.g. STRT>PWSU, RUN>HIB, CHRG>HIB). Rows come as columns plus rows; more: true means rows past limit were left out.",
"inputSchema": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"default": 20,
"maximum": 1000,
"minimum": 1,
"description": "how many sessions come back at once, newest first; when the answer says more, a narrower range shows the older ones"
},
"since": {
"type": "string",
"description": "the earliest time to include, in the bike's local time (America/Los_Angeles): a date or date-time such as 2026-09-10T14:30, or an age back from now such as -7d, -12h. Nothing is cut off at the start when left out"
},
"until": {
"type": "string",
"description": "the latest time to include, written like since; the range stops just before it. Nothing is cut off at the end when left out"
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"columns",
"rows"
],
"properties": {
"more": {
"type": "boolean",
"description": "true when rows past limit were left out; absent otherwise"
},
"rows": {
"type": "array",
"items": {
"type": "array",
"items": {}
},
"description": "one array per row, its values in this column order: id is the session's id, which other tools take; name is its name, e.g. b0194-001, or b0198-001.2 for a later part of a long session; board is the dongle that captured it; fw is that dongle's firmware version; boot is why the dongle booted, e.g. power-on; started is the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter; ended is the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter; lines is how many lines it captured; states is the bike's state changes it saw, in order, e.g. [\"RUN>HIB\"]"
},
"columns": {
"type": "array",
"items": {
"type": "string"
},
"description": "always id, name, board, fw, boot, started, ended, lines, states"
}
}
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description75/100
The bike's event log, oldest first: the main board's own stamped lines (state changes, contactors, charging, faults, hibernate) and the dongle's markers, which start with "dongle:". Each row is t, session (the id of the session holding it) and text. Rows come as columns plus rows; more: true means rows past limit were left out.
The description explains the capability, when to use it, and what to expect.
Inputs95/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
since
the earliest time to include, in the bike's local time (America/Los_Angeles): a date or date-time such as 2026-09-10T14:30, or an age back from now such as -7d, -12h. Nothing is cut off at the start when left out
Clear enough to supply this argument.
until
the latest time to include, written like since; the range stops just before it. Nothing is cut off at the end when left out
Clear enough to supply this argument.
pattern
keep lines containing this text, ignoring case, e.g. State change, Contactor, fault, Hibernat. All lines when left out
Clear enough to supply this argument.
include_dongle
also the dongle's own markers: session start and end, sleep, WiFi joins, pushes
Clear enough to supply this argument.
limit
how many lines come back at once, the latest in the range; when the answer says more, a narrower range shows the rest
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"type": "object",
"required": [
"columns",
"rows"
],
"properties": {
"more": {
"type": "boolean",
"description": "true when rows past limit were left out; absent otherwise"
},
"rows": {
"type": "array",
"items": {
"type": "array",
"items": {}
},
"description": "one array per row, its values in this column order: t is the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter; session is the id of the session holding the line; text is the line as the bike or the dongle wrote it; a dongle marker starts with dongle:"
},
"columns": {
"type": "array",
"items": {
"type": "string"
},
"description": "always t, session, text"
}
}
}
Original tool metadata
{
"name": "events",
"title": "Events",
"description": "The bike's event log, oldest first: the main board's own stamped lines (state changes, contactors, charging, faults, hibernate) and the dongle's markers, which start with \"dongle:\". Each row is t, session (the id of the session holding it) and text. Rows come as columns plus rows; more: true means rows past limit were left out.",
"inputSchema": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"default": 100,
"maximum": 1000,
"minimum": 1,
"description": "how many lines come back at once, the latest in the range; when the answer says more, a narrower range shows the rest"
},
"since": {
"type": "string",
"description": "the earliest time to include, in the bike's local time (America/Los_Angeles): a date or date-time such as 2026-09-10T14:30, or an age back from now such as -7d, -12h. Nothing is cut off at the start when left out"
},
"until": {
"type": "string",
"description": "the latest time to include, written like since; the range stops just before it. Nothing is cut off at the end when left out"
},
"pattern": {
"type": "string",
"description": "keep lines containing this text, ignoring case, e.g. State change, Contactor, fault, Hibernat. All lines when left out"
},
"include_dongle": {
"type": "boolean",
"default": true,
"description": "also the dongle's own markers: session start and end, sleep, WiFi joins, pushes"
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"columns",
"rows"
],
"properties": {
"more": {
"type": "boolean",
"description": "true when rows past limit were left out; absent otherwise"
},
"rows": {
"type": "array",
"items": {
"type": "array",
"items": {}
},
"description": "one array per row, its values in this column order: t is the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter; session is the id of the session holding the line; text is the line as the bike or the dongle wrote it; a dongle marker starts with dongle:"
},
"columns": {
"type": "array",
"items": {
"type": "string"
},
"description": "always t, session, text"
}
}
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description89/100
The figures the archive has parsed from the console's tables, to find the exact name series() takes. With no pattern the answer is commands: every name grouped by the console command that prints it. With one, the matches as columns plus rows: name, command, unit, samples (how many readings the archive holds), first and last time, and last_value.
The description explains the capability, when to use it, and what to expect.
Inputs89/100
Input documentation gives an agent enough context to populate the arguments.
pattern
part of a name, e.g. SOC, 12V, Temp, Current; with it, each match's unit, sample count, first and last time and last value. Every name, grouped by console command, when left out
{
"type": "object",
"properties": {
"more": {
"type": "boolean",
"description": "true when rows past limit were left out; absent otherwise"
},
"rows": {
"type": "array",
"items": {
"type": "array",
"items": {}
},
"description": "one array per row, its values in this column order: name is the reading's name, which series() takes; command is the console command that prints it; unit is its unit; empty or null when it has none; samples is how many readings the archive holds; first is the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter; last is the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter; last_value is the newest reading's value"
},
"columns": {
"type": "array",
"items": {
"type": "string"
},
"description": "always name, command, unit, samples, first, last, last_value"
},
"commands": {
"type": "object",
"description": "answers a call with no pattern instead of columns and rows: each console command mapped to the reading names it prints",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
Original tool metadata
{
"name": "reading_names",
"title": "Reading names",
"description": "The figures the archive has parsed from the console's tables, to find the exact name series() takes. With no pattern the answer is commands: every name grouped by the console command that prints it. With one, the matches as columns plus rows: name, command, unit, samples (how many readings the archive holds), first and last time, and last_value.",
"inputSchema": {
"type": "object",
"properties": {
"pattern": {
"type": "string",
"description": "part of a name, e.g. SOC, 12V, Temp, Current; with it, each match's unit, sample count, first and last time and last value. Every name, grouped by console command, when left out"
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"properties": {
"more": {
"type": "boolean",
"description": "true when rows past limit were left out; absent otherwise"
},
"rows": {
"type": "array",
"items": {
"type": "array",
"items": {}
},
"description": "one array per row, its values in this column order: name is the reading's name, which series() takes; command is the console command that prints it; unit is its unit; empty or null when it has none; samples is how many readings the archive holds; first is the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter; last is the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter; last_value is the newest reading's value"
},
"columns": {
"type": "array",
"items": {
"type": "string"
},
"description": "always name, command, unit, samples, first, last, last_value"
},
"commands": {
"type": "object",
"description": "answers a call with no pattern instead of columns and rows: each console command mapped to the reading names it prints",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description76/100
One reading over time, with its unit, min, max and first and last time. Points are [t, v] raw, or [t, mean, n] averaged. Rows come as columns plus rows; more: true means rows past limit were left out.
The description explains the capability, when to use it, and what to expect.
Inputs96/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
name
a reading's exact name, e.g. State_of_Charge, as reading_names() lists it
Clear enough to supply this argument.
since
the earliest time to include, in the bike's local time (America/Los_Angeles): a date or date-time such as 2026-09-10T14:30, or an age back from now such as -7d, -12h. Nothing is cut off at the start when left out
Clear enough to supply this argument.
until
the latest time to include, written like since; the range stops just before it. Nothing is cut off at the end when left out
Clear enough to supply this argument.
command
which console command's printout to read the name from, for a name several commands print (the answer's commands lists them). All of them when left out
Clear enough to supply this argument.
step_s
seconds per averaged point; 0 picks the smallest step that fits limit points and says it as step_s
Clear enough to supply this argument.
limit
how many points come back at once, the latest in the range; with step_s left at 0 a range holding more readings is averaged down to fit
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"type": "object",
"required": [
"name",
"unit",
"samples"
],
"properties": {
"max": {
"type": "number"
},
"min": {
"type": "number"
},
"last": {
"type": "string",
"description": "time of the last reading in the range"
},
"more": {
"type": "boolean",
"description": "true when earlier points were left out"
},
"name": {
"type": "string"
},
"rows": {
"type": "array",
"items": {
"type": "array",
"items": {}
},
"description": "the points, oldest first"
},
"unit": {
"type": [
"string",
"null"
],
"description": "empty or null when the reading has no unit"
},
"first": {
"type": "string",
"description": "time of the first reading in the range"
},
"step_s": {
"type": "integer",
"description": "present when the step was chosen to fit limit points"
},
"columns": {
"type": "array",
"items": {
"type": "string"
},
"description": "[t, v] for raw points, [t, mean, n] for averaged ones"
},
"samples": {
"type": "integer",
"description": "readings in the range, before averaging"
},
"commands": {
"type": "array",
"items": {
"type": "string"
},
"description": "present when several commands print the name; command picks one"
}
}
}
Original tool metadata
{
"name": "series",
"title": "Series",
"description": "One reading over time, with its unit, min, max and first and last time. Points are [t, v] raw, or [t, mean, n] averaged. Rows come as columns plus rows; more: true means rows past limit were left out.",
"inputSchema": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"description": "a reading's exact name, e.g. State_of_Charge, as reading_names() lists it"
},
"limit": {
"type": "integer",
"default": 200,
"maximum": 1000,
"minimum": 1,
"description": "how many points come back at once, the latest in the range; with step_s left at 0 a range holding more readings is averaged down to fit"
},
"since": {
"type": "string",
"description": "the earliest time to include, in the bike's local time (America/Los_Angeles): a date or date-time such as 2026-09-10T14:30, or an age back from now such as -7d, -12h. Nothing is cut off at the start when left out"
},
"until": {
"type": "string",
"description": "the latest time to include, written like since; the range stops just before it. Nothing is cut off at the end when left out"
},
"step_s": {
"type": "integer",
"default": 0,
"description": "seconds per averaged point; 0 picks the smallest step that fits limit points and says it as step_s"
},
"command": {
"enum": [
"status",
"charging",
"bms",
"pdu",
"in",
"faults",
"bms interface",
"controller",
"msc",
"dash info",
"ccm",
"obd",
"performance",
"state",
"stats",
"config"
],
"type": "string",
"description": "which console command's printout to read the name from, for a name several commands print (the answer's commands lists them). All of them when left out"
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"name",
"unit",
"samples"
],
"properties": {
"max": {
"type": "number"
},
"min": {
"type": "number"
},
"last": {
"type": "string",
"description": "time of the last reading in the range"
},
"more": {
"type": "boolean",
"description": "true when earlier points were left out"
},
"name": {
"type": "string"
},
"rows": {
"type": "array",
"items": {
"type": "array",
"items": {}
},
"description": "the points, oldest first"
},
"unit": {
"type": [
"string",
"null"
],
"description": "empty or null when the reading has no unit"
},
"first": {
"type": "string",
"description": "time of the first reading in the range"
},
"step_s": {
"type": "integer",
"description": "present when the step was chosen to fit limit points"
},
"columns": {
"type": "array",
"items": {
"type": "string"
},
"description": "[t, v] for raw points, [t, mean, n] for averaged ones"
},
"samples": {
"type": "integer",
"description": "readings in the range, before averaging"
},
"commands": {
"type": "array",
"items": {
"type": "string"
},
"description": "present when several commands print the name; command picks one"
}
}
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description75/100
The full text a console command printed, as captured: the tables series() reads figures from, and the parts it does not parse (the cell table in bms, faults, the firmware versions in in). Returns one capture: t (when), session (its id), command and output (the text).
The description explains the capability, when to use it, and what to expect.
Inputs91/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
command
the console command whose captured printout to return, e.g. bms for the cell table, faults, in for the firmware versions; portal is the page a captive portal served the board's push
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
at
look back to this moment and return the last output captured at or before it, written like since but as a wall-clock time, not a uNNNNNN stamp. Take one from the started or ended of sessions() or the t of events() or search(); the newest output when left out
Clear enough to supply this argument.
session
take the output only from this session, as sessions() lists it: its name, or its id written as text, e.g. "588". Any session when left out
Align the output schema with the tool’s documented result.
View output schema
{
"type": "object",
"required": [
"t",
"session",
"command",
"output"
],
"properties": {
"t": {
"type": "string",
"description": "when the output was captured: the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter"
},
"output": {
"type": "string",
"description": "the full text the command printed"
},
"command": {
"type": "string",
"description": "the command asked for"
},
"session": {
"type": "integer",
"description": "the id of the session it was captured in"
}
},
"additionalProperties": false
}
Original tool metadata
{
"name": "snapshot",
"title": "Snapshot",
"description": "The full text a console command printed, as captured: the tables series() reads figures from, and the parts it does not parse (the cell table in bms, faults, the firmware versions in in). Returns one capture: t (when), session (its id), command and output (the text).",
"inputSchema": {
"type": "object",
"required": [
"command"
],
"properties": {
"at": {
"type": "string",
"description": "look back to this moment and return the last output captured at or before it, written like since but as a wall-clock time, not a uNNNNNN stamp. Take one from the started or ended of sessions() or the t of events() or search(); the newest output when left out"
},
"command": {
"enum": [
"status",
"charging",
"bms",
"pdu",
"in",
"faults",
"bms interface",
"controller",
"msc",
"dash info",
"ccm",
"obd",
"performance",
"state",
"stats",
"config",
"portal"
],
"type": "string",
"description": "the console command whose captured printout to return, e.g. bms for the cell table, faults, in for the firmware versions; portal is the page a captive portal served the board's push"
},
"session": {
"type": "string",
"description": "take the output only from this session, as sessions() lists it: its name, or its id written as text, e.g. \"588\". Any session when left out"
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"t",
"session",
"command",
"output"
],
"properties": {
"t": {
"type": "string",
"description": "when the output was captured: the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter"
},
"output": {
"type": "string",
"description": "the full text the command printed"
},
"command": {
"type": "string",
"description": "the command asked for"
},
"session": {
"type": "integer",
"description": "the id of the session it was captured in"
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description79/100
Every captured line containing the query, oldest first, to find when something happened: the bike's events, the dongle's markers and lines the main board printed on its own. Each row is t, session (the id of the session holding the line), kind (event, dongle or mbb), command (always null) and text; session_lines() then shows the lines around it. Rows come as columns plus rows; more: true means rows past limit were left out.
The description explains the capability, when to use it, and what to expect.
Inputs88/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
query
the text to find, ignoring case: tried as a whole phrase, then as part of a line
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
since
the earliest time to include, in the bike's local time (America/Los_Angeles): a date or date-time such as 2026-09-10T14:30, or an age back from now such as -7d, -12h. Nothing is cut off at the start when left out
Clear enough to supply this argument.
until
the latest time to include, written like since; the range stops just before it. Nothing is cut off at the end when left out
Clear enough to supply this argument.
limit
how many lines come back at once, the latest in the range; when the answer says more, a narrower range shows the rest
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"type": "object",
"required": [
"columns",
"rows"
],
"properties": {
"more": {
"type": "boolean",
"description": "true when rows past limit were left out; absent otherwise"
},
"rows": {
"type": "array",
"items": {
"type": "array",
"items": {}
},
"description": "one array per row, its values in this column order: t is the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter; session is the id of the session holding the line; kind is event (the bike's own log), dongle (the dongle's markers) or mbb (a line the main board printed on its own, such as a banner or prompt, not an answer to a poll); command is always null; text is the line"
},
"columns": {
"type": "array",
"items": {
"type": "string"
},
"description": "always t, session, kind, command, text"
}
}
}
Original tool metadata
{
"name": "search",
"title": "Search",
"description": "Every captured line containing the query, oldest first, to find when something happened: the bike's events, the dongle's markers and lines the main board printed on its own. Each row is t, session (the id of the session holding the line), kind (event, dongle or mbb), command (always null) and text; session_lines() then shows the lines around it. Rows come as columns plus rows; more: true means rows past limit were left out.",
"inputSchema": {
"type": "object",
"required": [
"query"
],
"properties": {
"limit": {
"type": "integer",
"default": 50,
"maximum": 1000,
"minimum": 1,
"description": "how many lines come back at once, the latest in the range; when the answer says more, a narrower range shows the rest"
},
"query": {
"type": "string",
"description": "the text to find, ignoring case: tried as a whole phrase, then as part of a line"
},
"since": {
"type": "string",
"description": "the earliest time to include, in the bike's local time (America/Los_Angeles): a date or date-time such as 2026-09-10T14:30, or an age back from now such as -7d, -12h. Nothing is cut off at the start when left out"
},
"until": {
"type": "string",
"description": "the latest time to include, written like since; the range stops just before it. Nothing is cut off at the end when left out"
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"columns",
"rows"
],
"properties": {
"more": {
"type": "boolean",
"description": "true when rows past limit were left out; absent otherwise"
},
"rows": {
"type": "array",
"items": {
"type": "array",
"items": {}
},
"description": "one array per row, its values in this column order: t is the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter; session is the id of the session holding the line; kind is event (the bike's own log), dongle (the dongle's markers) or mbb (a line the main board printed on its own, such as a banner or prompt, not an answer to a poll); command is always null; text is the line"
},
"columns": {
"type": "array",
"items": {
"type": "string"
},
"description": "always t, session, kind, command, text"
}
}
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description77/100
One session's transcript in order, a stretch at a time. Returns the session's id and, as columns seq (record number), t, kind, command (always null), text. Rows come as columns plus rows; more: true means rows past limit were left out.
The description explains the capability, when to use it, and what to expect.
Inputs96/100
Input documentation gives an agent enough context to populate the arguments.
session
a session as sessions() lists it: its name (b0194-001, or b0198-001.2 for a later part of a long session), or its id written as text, e.g. "588"
Clear enough to supply this argument.
offset
where to continue from: the number of lines already read, to read a long session a stretch at a time
Clear enough to supply this argument.
limit
how many lines to return from offset on
Clear enough to supply this argument.
kinds
keep these kinds of line: event is the board's own log, dongle the dongle's markers, mbb what the board printed on its own. All kinds when left out
{
"type": "object",
"required": [
"session",
"columns",
"rows"
],
"properties": {
"more": {
"type": "boolean",
"description": "true when rows past limit were left out; absent otherwise"
},
"rows": {
"type": "array",
"items": {
"type": "array",
"items": {}
},
"description": "one array per row, its values in this column order: seq is the line's record number in the session's file; gaps are normal; t is the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter; kind is event, dongle or mbb, as search() says; command is always null; text is the line"
},
"columns": {
"type": "array",
"items": {
"type": "string"
},
"description": "always seq, t, kind, command, text"
},
"session": {
"type": "integer",
"description": "the session's id"
}
}
}
Original tool metadata
{
"name": "session_lines",
"title": "Session lines",
"description": "One session's transcript in order, a stretch at a time. Returns the session's id and, as columns seq (record number), t, kind, command (always null), text. Rows come as columns plus rows; more: true means rows past limit were left out.",
"inputSchema": {
"type": "object",
"required": [
"session"
],
"properties": {
"kinds": {
"type": "array",
"items": {
"enum": [
"event",
"dongle",
"mbb"
],
"type": "string"
},
"description": "keep these kinds of line: event is the board's own log, dongle the dongle's markers, mbb what the board printed on its own. All kinds when left out"
},
"limit": {
"type": "integer",
"default": 200,
"maximum": 1000,
"minimum": 1,
"description": "how many lines to return from offset on"
},
"offset": {
"type": "integer",
"default": 0,
"minimum": 0,
"description": "where to continue from: the number of lines already read, to read a long session a stretch at a time"
},
"session": {
"type": "string",
"description": "a session as sessions() lists it: its name (b0194-001, or b0198-001.2 for a later part of a long session), or its id written as text, e.g. \"588\""
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"session",
"columns",
"rows"
],
"properties": {
"more": {
"type": "boolean",
"description": "true when rows past limit were left out; absent otherwise"
},
"rows": {
"type": "array",
"items": {
"type": "array",
"items": {}
},
"description": "one array per row, its values in this column order: seq is the line's record number in the session's file; gaps are normal; t is the bike's local time as YYYY-MM-DDTHH:MM:SS.mmm, or uNNNNNN.mmm (seconds since the dongle booted) when the dongle's clock was not set yet; a range never matches the latter; kind is event, dongle or mbb, as search() says; command is always null; text is the line"
},
"columns": {
"type": "array",
"items": {
"type": "string"
},
"description": "always seq, t, kind, command, text"
},
"session": {
"type": "integer",
"description": "the session's id"
}
}
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description80/100
The dongle's state now, when it is on the network: the main board awake or asleep, the pack's charge, sleep plans, storage, where its clock comes from. One object; its output schema describes each part.
The description explains the capability, when to use it, and what to expect.
Inputs100/100
This tool declares no inputs, so argument descriptions are not needed.
{
"type": "object",
"required": [
"readings"
],
"properties": {
"readings": {
"type": "array",
"items": {
"type": "object",
"required": [
"n",
"g",
"v",
"u",
"age_s"
],
"properties": {
"g": {
"type": "string",
"description": "its group, e.g. pack, motor, 12v"
},
"n": {
"type": "string",
"description": "the reading's name"
},
"u": {
"type": "string",
"description": "unit, empty when it has none"
},
"v": {
"type": "number"
},
"age_s": {
"type": "integer",
"description": "seconds since it was read; -2 when it is from before this boot and the dongle's clock is not set yet"
}
}
},
"description": "empty until the dongle holds any reading"
}
}
}
Original tool metadata
{
"name": "live_readings",
"title": "Live readings",
"description": "The dongle's current figures, when it is on the network: each with its unit and age in seconds.",
"inputSchema": {
"type": "object",
"properties": {},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"readings"
],
"properties": {
"readings": {
"type": "array",
"items": {
"type": "object",
"required": [
"n",
"g",
"v",
"u",
"age_s"
],
"properties": {
"g": {
"type": "string",
"description": "its group, e.g. pack, motor, 12v"
},
"n": {
"type": "string",
"description": "the reading's name"
},
"u": {
"type": "string",
"description": "unit, empty when it has none"
},
"v": {
"type": "number"
},
"age_s": {
"type": "integer",
"description": "seconds since it was read; -2 when it is from before this boot and the dongle's clock is not set yet"
}
}
},
"description": "empty until the dongle holds any reading"
}
}
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description87/100
The text the dongle last captured from one console command (bms, charging, faults ...), read from the dongle over WiFi. It sends nothing to the bike's main board: the dongle polls on its own schedule, so the output can be older than now, and its age is not returned. Returns it verbatim as result.
The description explains the capability, when to use it, and what to expect.
Inputs66/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
name
the console command whose last captured output to read; the dongle polls these itself, so this is what it last read
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string",
"description": "the command's last output as the dongle holds it, verbatim"
}
}
}
Original tool metadata
{
"name": "live_command",
"title": "Last console output",
"description": "The text the dongle last captured from one console command (bms, charging, faults ...), read from the dongle over WiFi. It sends nothing to the bike's main board: the dongle polls on its own schedule, so the output can be older than now, and its age is not returned. Returns it verbatim as result.",
"inputSchema": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"enum": [
"status",
"charging",
"bms",
"pdu",
"in",
"faults",
"bms interface",
"controller",
"msc",
"dash info",
"ccm",
"obd",
"performance",
"state",
"stats",
"config"
],
"type": "string",
"description": "the console command whose last captured output to read; the dongle polls these itself, so this is what it last read"
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string",
"description": "the command's last output as the dongle holds it, verbatim"
}
}
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
Loading score analytics…
Put your MCP to the test
A few tasks worth trying with this server, chosen from its reviewed tools. These have not been run.
01SessionsSessions in a range, newest first: one per time the bike's main board woke, for a ride, a charge or a timed wake.
02EventsThe bike's event log, oldest first: the main board's own stamped lines (state changes, contactors, charging, faults, hibernate) and the dongle's markers, whi…
03Live statusThe dongle's state now, when it is on the network: the main board awake or asleep, the pack's charge, sleep plans, storage, where its clock comes from.
04Live readingsThe dongle's current figures, when it is on the network: each with its unit and age in seconds.
05SearchEvery captured line containing the query, oldest first, to find when something happened: the bike's events, the dongle's markers and lines the main board pri…
Want to run these tasks against your MCP server with us?
Zongle: Zero motorcycle console dongle setup, tools, quality score, publishing readiness, and alternatives.
How do I add Zongle: Zero motorcycle console dongle to Claude, ChatGPT, or Cursor?
Add Zongle: Zero motorcycle console dongle to Claude, ChatGPT, or Cursor by connecting its remote MCP URL in each client's MCP settings. In Claude, add a custom connector. In ChatGPT, add an MCP app. In Cursor, add an MCP server under Settings. The MCP URL is https://zongle.paulm.com/mcp.
Is Zongle: Zero motorcycle console dongle MCP ready for ChatGPT and Claude?
As of October 23, 2026, Zongle: Zero motorcycle console dongle scores 100/100 on Manufact's MCP publishing checklist. The scan meets ChatGPT publishing checks and meets Claude publishing checks. Passing these checks does not guarantee marketplace approval.
How clear is Zongle: Zero motorcycle console dongle's MCP tool documentation?
As of October 23, 2026, Zongle: Zero motorcycle console dongle scores 87/100 in Manufact's review of tool titles, descriptions, input and output schemas, and behavior annotations. The review covers 10 of 10 discovered tools. The quality score measures documentation clarity; runtime behavior and marketplace readiness require separate checks.
What are the best alternatives to Zongle: Zero motorcycle console dongle?
As of October 24, 2026, alternatives to Zongle: Zero motorcycle console dongle in data-analytics on the Manufact MCP leaderboard include Epicure, Newsflash, Point Topic, Pricing Optimizer AI, and StatCite.
How can Zongle: Zero motorcycle console dongle improve its MCP documentation?
series is the lowest-scoring reviewed tool at 79/100. The title clearly communicates the tool’s action and subject. Keep it concise. Open its review for feedback and a copyable fix prompt, then rerun the documentation review after updating your tool metadata.
Not your MCP?
Review any public or OAuth MCP server for protocol compatibility, tool documentation, and ChatGPT and Claude publishing readiness. No account required.