mcp-kodi
The mcp-kodi server lets an AI assistant control Kodi media players via an MCP interface, enabling comprehensive media management and playback across one or more Kodi instances.
Playback Transport
Play, pause, stop, skip to next/previous items
Play any specific file by path (in-library or not)
Volume & Audio
Adjust volume by relative step, mute/unmute, read current volume/mute state
Now Playing & Notifications
Query current playback state and media info (
nowplaying)Display toast notifications on the Kodi screen (title, message, icon, duration)
Media Search & Discovery
Search music, TV shows, and movies by name, actor, director, season, episode, etc. with paging
List/search contributors (artists, bands, actors, directors) and see where they appear
Inspect audio tracks and subtitles of movies/episodes before playback
Queue Management
Append or insert items into the playback queue
Read current or named playlists without modifying them
Clear all active queues (audio, video, picture) while keeping current item playing
Audio/Subtitle Switching
Switch the active audio track and/or subtitle stream during video playback
Playback History
Query a local playback log with filters (time window, media type, artist, free text, specific IDs); works even when Kodi is offline
Instance Configuration Management
Read, add, update, or remove Kodi instance configurations; passwords are never exposed
Raw JSON-RPC Passthrough (Escape Hatch)
Send any raw JSON-RPC method directly to Kodi; disabled by default and must be manually enabled per instance via
allow_rpc: truein the config — the AI cannot enable this itself
Controls a Kodi media player via its JSON-RPC API, enabling transport control (play, pause, stop), volume adjustment, search/discovery of media, queue management, playback history, and an escape hatch for arbitrary Kodi JSON-RPC methods.
mcp-kodi
An MCP server that lets an AI assistant control a Kodi media player over Kodi's JSON-RPC API. Written in C on the GLib stack.
There is no user-facing CLI: you talk to the AI, the AI calls this server's tools, and the server speaks JSON-RPC to Kodi. The only interface is MCP over stdio.
Where this is going. The plan is a complete, full-featured package that lets any MCP-compatible AI transform the entire media-player experience — not just press buttons, but reinvent how you discover, queue, and enjoy your media. Tell the assistant what you're in the mood for and let it run the room: build the evening's lineup, pick up where you left off last night, adapt on the fly, and surface things you'd never have found yourself. We're aiming for something genuinely new — a mind-blowingly different way to live with your media player.
Status — early, but already remarkable (v0.2.0dev). A growing set of dedicated, purpose-built tools covers transport, volume, search, queue management, and playback history. What makes the build capable beyond that list is the
rpcescape hatch (see below): an opt-in passthrough to any Kodi JSON-RPC method. Between the first-class tools and that escape hatch, an assistant can already drive nearly everything Kodi exposes — remarkable enough that we decided to publish early rather than wait for the full vision to land. Expect frequent releases.
What it can do
Each tool targets a configured Kodi box by key (instance); omit it and the
configured default box is used (with one exception: history spans all
boxes when instance is omitted).
Transport & audio
Tool | What it does |
| Press Play on the remote — resume or begin playback on the target box. |
| Press Pause — pause the active player. |
| Press Stop — stop the active player and clear the playlist it was consuming, so no queued items linger. |
| Press Skip Next — advance to the next track/chapter in the active playlist. |
| Press Skip Previous — go to the previous track/chapter (or restart the current item). |
| Adjust the volume by a relative signed step (percentage points); step |
| Mute the box's audio output. |
| Unmute the box's audio output. |
| Report what is playing without changing anything — also a reachability + state probe. |
| Show a notification toast on the box's screen — title + message, with an optional icon ( |
Search & discovery
Tool | What it does |
| Find playable leaf files by name across |
| Find or list people — bands, solo artists, composers, actors, directors — by optional name substring and/or |
| Inspect a movie or episode's audio tracks and subtitles before playback, from Kodi's cached |
| Switch the audio track and/or subtitle of the video now playing, by the |
Playback & queue
Tool | What it does |
| Play one file by path (typically a |
| Append an item behind the one now playing (a |
| Read a queue without changing it — the active player's playlist, or a named one ( |
| Empty all queues (audio, video, picture) in one call. The current item keeps playing — only the items queued behind it are removed. Not undoable; inspect with |
Bookkeeping & escape hatch
Tool | What it does |
| List recently played items from the local playback log, written as a side effect of every playback-affecting call. Optional ISO-8601 |
| Read or modify the server's own instance config ( |
| Escape hatch — send a raw JSON-RPC method to Kodi and return its reply unchanged. Off by default; opt-in per instance (see below). |
Most action tools return a small player-state snapshot — { "state": "playing"|"paused"|"stopped", "type", "time", "totaltime", "progress", "nowplaying": { "media", "id", "file", "label", "title", … } } — keeping the
player status (state/type/time/totaltime plus a legible progress clause
like "15:38 / 46:40 (33%)") at the top and nesting the loaded media under
nowplaying, with its per-media fields where they apply (artist, album,
track, showtitle, season, episode) — so the assistant always sees the
effect of its action: this covers
play/pause/stop, playfile, queue, dropplaylists, and nowplaying. The
audio tools volume/mute/unmute return { "muted", "volume" } (volume
also adds the min/max bounds). The read tools (searchmedia,
contributors, getplaylist, history) return their own paged result
envelopes.
Every tool except rpc declares these shapes as an MCP outputSchema
(spec revision 2025-06-18) and mirrors each successful result as
structuredContent alongside the JSON text block, so schema-aware clients
can validate and consume results without parsing. Each description also
states the result shape inline — the channel every client shows the model.
rpc declares none: it returns Kodi's raw reply verbatim, which has no
fixed shape.
The rpc escape hatch
rpc POSTs any JSON-RPC method you name to the target box and hands back Kodi's
raw result, unshaped:
// e.g. raise the GUI volume, activate a window, send an input action…
rpc { "instance": "hall", "method": "GUI.ActivateWindow", "params": { "window": "home" } }This is powerful and unconstrained, so it is disabled by default and gated
per instance. A box permits rpc only when its config object carries
"allow_rpc": true. That flag is granted only by hand-editing config.json —
it is intentionally not one of the fields the instances tool can write, so
the assistant can never enable its own escape hatch. Opting a box in is an
explicit, out-of-band human decision; calling rpc on a box that hasn't opted in
returns a clean error and makes no Kodi request.
See the full Kodi method surface in docs/kodi-jsonrpc-catalog.md.
Related MCP server: mcp-mpv-player
Configuration
Set up Kodi for remote control
Before mcp-kodi can reach a box, that Kodi has to allow remote control. In Kodi,
open Settings → Services → Control and turn on Allow remote control via
HTTP, then set a username and password right there. Those same credentials
go into this server's config as auth, in user:pass form.
mcp-kodi speaks HTTPS, so for normal use you put a small reverse proxy in
front of Kodi's plain-HTTP control port. Caddy with
tls internal is the easy choice: it terminates HTTPS and forwards to Kodi on
localhost. Point the instance's host at the proxy and set insecure: true
to accept its self-signed certificate. The full step-by-step walkthrough — the
exact Kodi menus, installing Caddy, and the Caddyfile — is in
docs/kodi-server-setup.md.
Most Kodi players already sit on a home LAN behind a router/firewall and are not exposed to the internet, so turning on the HTTP control interface there is generally safe. The login/password and the HTTPS proxy add defence in depth — just keep the proxy on a trusted network and don't forward its port to the open internet.
Registering a Kodi instance
There are two ways to add a box. The simplest is to let the AI do it: once
the MCP server is loaded, just tell the assistant about your Kodi — its address
and login — and it registers the instance for you through the instances tool
(set), writing the entry into the config file.
You can also do it by hand, by editing config.json directly. Two things
are deliberately off-limits to the AI, so hand-editing is the only way to set
them:
The password.
authis write-only — theinstancestool never returns a stored password, so the assistant can register a box but can never read back the credentials. If you'd rather the AI never see the password at all, type it into the file yourself.The escape hatch.
allow_rpcis not a field theinstancestool can write, so the assistant can never grant itself the unrestrictedrpcpassthrough. Enabling it is always an explicit, out-of-band human edit.
The config file
The server reads ${XDG_CONFIG_HOME:-~/.config}/mcp-kodi/config.json. It holds a
map of named Kodi instances and names one default:
{
"version": 2,
"default": "hall",
"instances": {
"hall": { "name": "Living Room TV", "host": "hall.example.local:8443", "auth": "kodi:<password>", "scheme": "https", "insecure": true, "allow_rpc": true },
"bedroom": { "name": "Bedroom", "host": "bedroom.example.local:8443", "auth": "kodi:<password>", "scheme": "https", "insecure": true }
}
}Field | Meaning |
instance key | The short id every tool references ( |
| The key used when a tool omits |
| Optional human-readable label, surfaced in the tool schema. |
|
|
| HTTP Basic credentials as |
|
|
|
|
|
|
The file is created 0600 in a 0700 directory (it holds passwords) and is
written back atomically when the instances tool changes it.
No config file? A single box can be defined entirely from the environment,
applied to an implicit default instance: KODI_HOST, KODI_AUTH,
KODI_SCHEME, and -k in KODI_CURL_OPTS (→ insecure). With neither a file
nor env, the server exits with a clear error telling you to configure.
A legacy version: 1 flat file (single top-level host/auth/…) is read as one
instance named default and rewritten in the version: 2 shape on the next save.
Note: config is read once at startup. After hand-editing
config.json(e.g. to setallow_rpc), restart the server so it re-reads the file.
Registering with an MCP client
Claude Code
# user scope makes the tools available in every project
claude mcp add --scope user kodi -- /path/to/mcp-kodi/src/mcp-kodiClaude Desktop / other MCP clients
Add a stdio server entry pointing at the binary:
{
"mcpServers": {
"kodi": {
"command": "/path/to/mcp-kodi/src/mcp-kodi"
}
}
}Once registered, ask your assistant things like "what's the player doing in the
living room?" (nowplaying), "find Pink Floyd's Animals and play it" (searchmedia →
playfile), or "mute the bedroom" (mute).
Security notes
config.jsonstores Kodi passwords in plaintext, mode0600. Protect it like any other credential file.insecure: truedisables TLS certificate verification for that box. It is the right choice behind Caddy'stls internalself-signed cert, but means the connection is encrypted, not authenticated against a CA — keep the proxy on a trusted network.The
rpcescape hatch can invoke any JSON-RPC method (including destructive ones likeSystem.Shutdown). It stays off until you deliberately setallow_rpc: truefor a specific box. Enable it only where you trust the assistant to operate unconstrained.
License
Copyright © 2026 Laszlo Pere <laszlopere@gmail.com>. An independent, clean-room implementation.
Free software, licensed under the GNU General Public License v3.0. You may redistribute and/or modify it under those terms; it comes with no warranty. See LICENSE for the full text.
Support this project
If this project is useful to you, please consider supporting it through GitHub Sponsors. Every bit of support keeps it alive — funding the time to ship the frequent releases this is built on, and to chase the full vision.
And if you're still on the fence: ask your Claude whether this project is good for you — and if it recommends it (as most Claude do), support it by becoming a sponsor.
Available Tools
22 toolsaudio_and_subtitle_infoA
Inspect a movie or episode's audio tracks and subtitles BEFORE playback, from Kodi's cached streamdetails (no playback). Name the item by type+id (a searchmedia movie/episode row) or by file. Returns { "file", "audio":[{ "index", "codec", "channels", "language" }], "subtitle":[{ "index", "language" }], "video":[…] }. Embedded streams only: external .srt sidecars and files Kodi hasn't scanned come back as empty arrays; "index" maps to the audio/subtitle setters for embedded streams.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Library id of the item to inspect — the `movieid`/`episodeid` of a `searchmedia` result row, matching `type`. Give exactly one of `id` or `file`. | |
| file | No | Path of the file to inspect — the `file` field of a `searchmedia` result row; any path Kodi can reach works. Streamdetails are only populated for files Kodi has scanned into its library. Give exactly one of `id` or `file`. | |
| type | No | Kind of library id passed in `id` — picks the item key (movieid/episodeid). Required with `id`; not used with `file`. Songs are not accepted: audio files carry no selectable audio-track or subtitle streams. | |
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| file | Yes | The resolved file path of the inspected item. |
| audio | Yes | Embedded audio tracks, in stream order. |
| video | Yes | Video streams, in stream order. |
| subtitle | Yes | Embedded subtitle tracks, in stream order. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does so well: it discloses the cached-source behavior (no playback), the embedded-only limitation, the failure mode where external .srt sidecars and unscanned files yield empty arrays, and the meaning of "index" as a handle for the setters. These are exactly the non-obvious traits 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 and scope, then constraints, then return shape — every sentence earns its place. It is dense and information-packed, with the streamdetails limitation and index mapping packed into the tail, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a pre-playback read tool with an output schema, no annotations, and fully documented params, the description covers everything an agent needs: purpose, naming inputs, output shape, and the embedded-only caveat. Even though the output schema exists, restating the return shape harms nothing.
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 still adds value beyond the schema by tying id/file back to their origin (a searchmedia movie/episode row) and restating the mutually-exclusive naming choice, giving semantic grounding rather than duplicating field 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?
States a specific verb and resource (inspect audio tracks and subtitles) plus a precise scope: pre-playback, from Kodi's cached streamdetails. This cleanly separates it from the sibling setters (set_audio_and_subtitle) and the playback tools, 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?
It establishes the key usage context (inspect BEFORE playback, no playback triggered) and points at the relevant alternatives by referencing the audio/subtitle setters that consume the returned "index" and searchmedia rows that supply the id/file. It stops short of an explicit when-not-to-use or a named sibling, so it is clear context rather than full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
contributorsA
Find or list contributors (bands, solo artists, composers, actors, directors): optional name substring, optional type (band/composer/actor/director) — e.g. {type: "band"} lists all bands. Rows {name, in: [albums|songs|movies|tvshows]} say where each name yields hits — feed the exact name back into searchmedia to drill. Returns { "total", "returned", "offset", "truncated", "rows" }.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Person name to look for (substring, case-insensitive): a band, solo artist, composer, actor, or director. Omit to list everyone (of `type` when given). | |
| type | No | Contributor kind to list. band = album-level music artist (closest Kodi gets to a band — includes headline solo artists); composer/actor/director are literal. Omit for all kinds. "List all bands" = {type: "band"} with no name. | |
| count | No | When true, return only the total match count (zero rows). | |
| limit | No | Max rows to return (default 50, max 500). Page with offset. | |
| offset | No | Number of rows to skip — paginate together with limit. | |
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| rows | Yes | The matching people, merged and sorted by name. |
| total | Yes | Full match count, before any paging. |
| offset | Yes | Rows skipped before this page. |
| returned | Yes | Rows in this page. |
| truncated | Yes | Whether matches remain beyond this page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses behavior: the tool is read-only, returns a structured object with total/returned/offset/truncated/rows, and explains that rows contain a 'name' and an 'in' array indicating where the name appears. The truncation signal and pagination implications are clear.
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 with zero waste. The first sentence bundles purpose, parameters, and an example. The second sentence covers output structure and integration with sibling tool. Every part 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?
Given the tool has 6 parameters (none required), an enum, and an output schema, the description covers all key aspects: usage patterns, output format, pagination hints, and integration with searchmedia. No gaps remain for an agent to misinterpret.
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 baseline is 3. The description adds value by explaining how parameters interact (e.g., 'Omit to list everyone (of type when given)', using count to return only total, and the pagination pattern). It gives a concrete example ('List all bands = {type: "band"} with no name') that clarifies 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?
Description opens with a specific verb-object pair ('Find or list contributors') and immediately clarifies the resource (bands, solo artists, composers, actors, directors). It distinguishes itself from sibling searchmedia by explaining that the output name is meant to be fed back into searchmedia for drilling. This makes the tool's role clear and complementary.
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 explains when to use the tool (to list contributors by type or search by name) and provides a concrete downstream action ('feed the exact name back into searchmedia'). It does not explicitly state when not to use it or list alternatives, but the context is sufficient for correct invocation among the siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dropplaylistsA
Empty all queues: clear the audio, video and picture playlists in one call. The current item keeps playing — only the queued items behind it are removed — so playback is never interrupted. Not undoable; inspect with getplaylist first if the content matters. Returns the player-state snapshot — whatever was playing still is, with nothing queued behind it.
| Name | Required | Description | Default |
|---|---|---|---|
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| time | No | Playback position { hours, minutes, seconds, milliseconds }. |
| type | No | The active player kind. |
| audio | No | Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector. |
| state | Yes | Playback state; "stopped" means nothing is loaded. |
| progress | No | Legible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length. |
| subtitle | No | Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector. |
| totaltime | No | The item's duration, same shape as time. |
| nowplaying | No | The loaded media (present whenever something is loaded): { media (song/episode/movie/…; "unknown" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does so: it defines exactly what is destroyed (only queued items behind the current one), guarantees playback continues uninterrupted, warns the operation is not undoable, and describes the resulting player state. This is precisely the destructive/reversibility context 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?
Four short sentences, each earning its place: scope, effect on current playback, reversibility warning, return state. The core action is front-loaded and there is no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Although an output schema exists (and a return description is therefore optional), the description still tells the agent what the snapshot will look like. Combined with the destruction scope and irreversibility warning, nothing needed to call this tool safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for the single 'instance' parameter, so the schema fully documents it. The description adds nothing about the instance parameter (or its default), so the baseline 3 applies rather than a higher score.
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: 'Empty all queues: clear the audio, video and picture playlists in one call.' It states scope (all three playlists at once) and implicitly distinguishes itself from sibling getplaylist, which it names. An agent can tell this apart from stop/skipnext 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 gives a clear precondition — 'Not undoable; inspect with getplaylist first if the content matters' — which routes to the alternative sibling and warns about irreversibility. It stops short of an explicit when-not-to-use statement (e.g. how it differs from stop), so it is clear context rather than full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
getplaylistA
Read the queue without changing it: the items of the active player's playlist — or of a named one (audio/video/picture), which always wins — plus the position of the now-playing item. An empty queue is an empty list. Returns { "type"?, "total", "position"?, "items": [ { "id", "file", "label", "type" } ] }.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Which playlist to read. Always wins when provided — reads that playlist even while another plays, the only way to inspect an inactive queue. Omitted reads the active player's playlist. | |
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| type | No | The playlist read, when one was resolved. |
| items | Yes | The queued items, in playback order. |
| total | Yes | Number of queued items. |
| position | No | Index of the now-playing item — present only when the playlist read is the active player's own. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It explicitly states the tool is non-destructive ('Read the queue without changing it'), describes the return format, and covers edge cases like an empty queue returning an empty list. It also reveals the override behavior of the 'type' parameter. This is good behavioral 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?
The description is extremely concise: two sentences that front-load the purpose and then provide additional context. Every sentence serves a purpose without unnecessary elaboration.
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 low complexity (2 optional parameters, output schema present), the description is fairly complete. It covers the return structure, empty queue behavior, and the parameter override. It could mention error scenarios (like invalid instance or no player active), but for a read-only tool this is not critical.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description adds value beyond the schema by explaining that specifying a type is 'the only way to inspect an inactive queue' and that the named playlist 'always wins'. This supplements the schema description for the 'type' parameter. The 'instance' parameter is not elaborated, but the schema already covers it adequately.
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 states it reads the queue without modifying it, and specifies the resource as the active player's playlist or a named one (audio/video/picture). The verb 'Read' and resource are explicit, and it distinguishes from sibling tools like 'nowplaying' (which likely shows only the current item) by indicating it returns the full playlist and position.
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 context for when to use the tool (reading the queue) and notes that a named playlist 'always wins', allowing inspection of inactive queues. It implicitly suggests not to use this for changing state, and sibling tools like 'play', 'pause', 'stop' are for control. However, it does not explicitly state when not to use or name alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
historyA
List recently played items from the local playback log. Filter with an ISO-8601 window (since/until), media/kind/artist, a free-text match or an exact id; page with limit/offset/order, or ask for a count only. An omitted instance returns all boxes. Reads only the local log — no Kodi call, so it works even when no box is reachable. Returns { "total", "returned", "offset", "truncated", "entries": [ { "at", "instance", "kind", "media", "title", "artist", … } ] }.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Exact library id to match ("every time THIS item played"). Ids are per media type, so pair with media; feed back a searchmedia or getplaylist row's id. | |
| kind | No | Keep only entries of this broad kind: audio or video — e.g. "what music did I play". | |
| count | No | When true, return only the total match count (zero entries) — a cheap "how many times / how much did X play". | |
| limit | No | Max entries to return (default 50, max 1000). When more match, the reply sets "truncated": true — page the rest with offset. | |
| match | No | Free-text substring (case-insensitive) over an entry's human fields — title, album, show, label and artist — to narrow the log without knowing ids. | |
| media | No | Keep only entries of this media kind (song/episode/movie/musicvideo/picture/channel) — e.g. "movies only". | |
| order | No | Result order: "newest" first (default) or "oldest" first to replay a session in the order it happened. | |
| since | No | Only entries at or after this ISO-8601 time (e.g. "2026-06-01T00:00:00Z"). Omitted = from the beginning of the log. Compute relative windows ("last 7 days") yourself. | |
| until | No | Only entries at or before this ISO-8601 time. Omitted = up to now. | |
| artist | No | Keep only entries whose performer contains this (substring, case-insensitive) — the music-by-artist filter ("everything Pink Floyd I played"). Only as good as the captured artist tag. | |
| offset | No | Number of matching entries to skip before this page — paginate together with limit, keeping the same order. | |
| instance | No | Restrict to one Kodi instance by key. Omitted returns entries from ALL instances — note this differs from other tools, where an omitted instance means the default box. |
Output Schema
| Name | Required | Description |
|---|---|---|
| since | No | The window's lower bound, echoed when one was given. |
| total | Yes | Full match count, before any paging. |
| until | No | The window's upper bound, echoed when one was given. |
| offset | Yes | Rows skipped before this page. |
| entries | Yes | The matching history records. |
| instance | No | The instance filter, echoed when one was given. |
| returned | Yes | Rows in this page. |
| truncated | Yes | Whether matches remain beyond this page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses that it reads only local log, requires no Kodi call, works even when no box reachable, and explains the behavior of omitted instance (returns all boxes). Since no annotations are provided, the description fully covers behavioral traits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-structured within a single paragraph. It front-loads the main purpose, then systematically covers filters, pagination, behavioral notes, and return format. Every sentence adds value without repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given high complexity (12 parameters, rich filtering, pagination, output schema), the description is complete. It covers all usage aspects, behavioral notes, and the return structure, leaving no ambiguity for an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Adds significant meaning beyond a fully covered schema (100% coverage). For instance, explains that omitted instance differs from other tools, advises computing relative windows for since/until, describes default/max for limit and truncated flag, explains offset pagination, order use case, count as cheap total, media/kind examples, artist substring limitation, match field scope, and id pairing with media.
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 states the tool lists recently played items from the local playback log, with specific verb and resource. It distinguishes from sibling tools like nowplaying, getplaylist, and searchmedia by focusing on historical playback log.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance on when to use, including filtering options (ISO-8601 window, media/kind/artist, free-text, exact id), pagination (limit/offset/order), and a note that omitted instance returns all boxes, differing from other tools. Also implies alternatives for library search.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
instancesA
Read or modify the configured Kodi instances (action: get/set/remove). Manages the MCP server's own config, not a Kodi device. Returns { "default", "instances": [ { "key", "host", "scheme", "insecure", "has_auth", "allow_rpc", … } ] }.
| Name | Required | Description | Default |
|---|---|---|---|
| key | No | Instance key — the short id tools target. Required for "set" and "remove". | |
| auth | No | HTTP Basic credentials as "user:pass" ("set"). Write-only: never returned by "get". | |
| host | No | Kodi host as "host[:port]" ("set"). | |
| name | No | Human-readable display label ("set"). | |
| action | Yes | Operation: "get" lists configured instances, "set" creates/updates one, "remove" deletes one. | |
| scheme | No | URL scheme, "http" or "https" ("set"; default "https"). | |
| default | No | When true on "set", make this instance the default. | |
| insecure | No | Accept a self-signed TLS certificate, like curl -k ("set"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| default | Yes | Key of the default instance, or null when none is configured. |
| instances | Yes | The configured instances, in sorted key order. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It explains the tool's scope (server config), actions, and return structure. It also notes that auth is write-only, adding important behavioral detail beyond 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?
The description is extremely concise: one sentence plus a compact return format listing. It front-loads the purpose and includes no filler. 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?
Given the tool's complexity (8 parameters, 1 required, no nested objects), the description covers the overall purpose, scope, and return structure. It is complete enough for an AI agent to understand usage without additional context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, providing baseline 3. The description adds value by summarizing actions, showing the output format, and noting the write-only nature of auth, which goes beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool reads or modifies configured Kodi instances, with explicit actions (get/set/remove). It distinguishes from sibling tools by clarifying it manages the MCP server's own config, not a Kodi device.
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 specifies that the tool manages the MCP server's own config, implying it is not for direct Kodi control. While it doesn't list explicit alternatives, the scope is clear, and sibling tools cover other functions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
muteA
Mute the target instance's audio output. Returns { "muted", "volume" }.
| Name | Required | Description | Default |
|---|---|---|---|
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| muted | Yes | Whether audio output is muted. |
| volume | Yes | The application volume, 0-100. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. It discloses the return structure (muted, volume) but lacks details on side effects, idempotency, or prerequisites beyond the parameter.
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 two sentences with no fluff, front-loading the action and return value, making it efficient and immediately informative.
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 tool with one optional parameter and an output schema, the description covers the core functionality and return. It could mention idempotency or behavior when already muted, but is adequate for most use cases.
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 description adds no information beyond the schema's parameter description, which already explains the 'instance' parameter and default behavior.
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 specifies a concrete verb ('Mute') and resource ('target instance's audio output'), clearly distinguishing it from sibling tools like 'unmute' and 'volume'.
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 (to silence audio output) but does not explicitly state when to use it versus alternatives like 'unmute' or 'volume', nor does it provide any exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
notifyA
Show a notification toast on the Kodi box's screen: a title and message, with an optional icon ("info"/"warning"/"error" or any image path/URL) and display time in milliseconds. Doesn't touch playback. Returns { "shown", "title", "message", "displaytime", "image"? }.
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Icon for the toast: one of the keywords "info", "warning" or "error" for a built-in icon, or any image path/URL the Kodi box can reach. Omitted uses Kodi's default icon. | |
| title | Yes | Notification title — the bold heading of the toast. | |
| message | Yes | Notification body text shown beneath the title. | |
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). | |
| displaytime | No | How long the toast stays on screen, in milliseconds. Omitted uses Kodi's default of 5000; Kodi clamps very small values to its own minimum. |
Output Schema
| Name | Required | Description |
|---|---|---|
| image | No | The icon keyword or image path that was used, present only when one was supplied. |
| shown | Yes | Always true — the notification was handed to Kodi. |
| title | Yes | The title that was shown. |
| message | Yes | The message that was shown. |
| displaytime | Yes | The display time in milliseconds — the requested value, or 5000 (Kodi's default) when none was given. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden: it discloses that the tool is non-playback-affecting, that the icon and display time are optional, that defaults exist (default icon, 5000ms), and that Kodi clamps small values. That is solid disclosure of side effects and edge behavior for a UI-affecting tool, though it does not state whether the toast is queued, whether it blocks, or permission requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the action and scoping, then parameters. Tight and waste-free overall, though the trailing return-shape sentence partially duplicates the existing output schema and is the weakest-earning clause.
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 5 params at 100% schema coverage, an output schema present, and no nested objects, the description supplies everything an agent needs: purpose, playback-neutral scope, parameter defaults, and clamping behavior. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter (image, title, message, instance, displaytime) is already fully documented in the schema, including the info/warning/error keywords and the ms unit. The description largely restates those same facts rather than adding syntax, format, or constraint details beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Show a notification toast on the Kodi box's screen') and immediately disambiguates from the entire playback-oriented sibling set with 'Doesn't touch playback.' An agent can identify this as the non-playback UI-notification tool 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?
The negative scoping statement ('Doesn't touch playback') tells the agent when this tool is appropriate relative to nowplaying/play/pause/etc., and the description implies this is for user-facing status messaging. However, it never names an explicit alternative or a positive trigger condition, so it stops short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nowplayingA
Report what is playing on the target instance without changing anything — also a reachability and state probe. Returns the player-state snapshot { "state", "type", "time", "totaltime", "progress", "audio", "subtitle" (audio/subtitle for video: count + current track), "nowplaying": { "media", "id", "title", "artist", … } }; { "state": "stopped" } when idle.
| Name | Required | Description | Default |
|---|---|---|---|
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| time | No | Playback position { hours, minutes, seconds, milliseconds }. |
| type | No | The active player kind. |
| audio | No | Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector. |
| state | Yes | Playback state; "stopped" means nothing is loaded. |
| progress | No | Legible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length. |
| subtitle | No | Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector. |
| totaltime | No | The item's duration, same shape as time. |
| nowplaying | No | The loaded media (present whenever something is loaded): { media (song/episode/movie/…; "unknown" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does well: it declares the call is non-mutating, discloses the exact returned snapshot fields, and specifies the idle return shape. It omits what happens when the instance is unreachable or how the target is resolved, which a probe tool would ideally cover.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose and safety statement are well front-loaded, but the long inline JSON snapshot dump largely restates the output schema that already exists. The opening sentence earns its place; the return-shape enumeration is padding against structured data.
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?
Purpose, safety profile, and idle-state behavior are all covered, and the output schema handles return values, so an agent has enough to call it correctly. The one real gap is failure/unreachable behavior for a tool explicitly framed as a reachability probe.
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?
Only one parameter and schema description coverage is 100%, so the schema already documents 'instance' and its default fully. The description adds no further semantics (no format, no fallback behavior), which is the baseline 3 case.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Report what is playing on the target instance') and adds a second explicit role as a 'reachability and state probe'. This clearly separates it from the mutating siblings play/pause/stop, which an agent can infer 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 phrase 'without changing anything' and the reachability-probe framing give clear context for when to pick this over the play/pause/stop siblings, and the idle case ('{ "state": "stopped" } when idle') tells the agent how to read a null result. No explicit exclusions or named alternatives, 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.
pauseB
Press Pause on the Kodi remote: pause the active player on the target instance. Returns the player-state snapshot { "state", "type", "time", "totaltime", "progress", "nowplaying": { "media", "id", "title", "artist", … } }.
| Name | Required | Description | Default |
|---|---|---|---|
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| time | No | Playback position { hours, minutes, seconds, milliseconds }. |
| type | No | The active player kind. |
| audio | No | Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector. |
| state | Yes | Playback state; "stopped" means nothing is loaded. |
| progress | No | Legible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length. |
| subtitle | No | Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector. |
| totaltime | No | The item's duration, same shape as time. |
| nowplaying | No | The loaded media (present whenever something is loaded): { media (song/episode/movie/…; "unknown" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses the return payload shape and that the action applies to the target instance, but says nothing about what happens when no player is active, whether the call is idempotent, or any permission/auth requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core action before the return detail. Slightly padded by enumerating the returned object's keys, which the output schema already defines.
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 spelling out the snapshot keys is partly redundant, and the behavioral side of a mutating player control (idle-player errors, idempotency) is left uncovered. Adequate but incomplete for a no-annotation 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?
Only one optional parameter and schema description coverage is 100%, so the schema already documents the default-instance behavior. The description adds no syntax or format detail beyond the schema, making the baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('pause the active player on the target instance'), which is precise and clearly distinct from the adjacent play and stop siblings. It does not explicitly contrast itself with stop/skipnext, but the action is unambiguous 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?
There is no when-to-use guidance, no mention of prerequisites, and no naming of alternatives such as stop versus pause. The usage is only inferable from the name and the phrase 'pause the active player'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
playA
Press Play on the Kodi remote: resumes paused playback only — it cannot start new content (with nothing loaded it is a no-op); use playfile to start something. Returns the player-state snapshot { "state", "type", "time", "totaltime", "progress", "nowplaying": { "media", "id", "title", "artist", … } }.
| Name | Required | Description | Default |
|---|---|---|---|
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| time | No | Playback position { hours, minutes, seconds, milliseconds }. |
| type | No | The active player kind. |
| audio | No | Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector. |
| state | Yes | Playback state; "stopped" means nothing is loaded. |
| progress | No | Legible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length. |
| subtitle | No | Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector. |
| totaltime | No | The item's duration, same shape as time. |
| nowplaying | No | The loaded media (present whenever something is loaded): { media (song/episode/movie/…; "unknown" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden: it discloses the no-op behavior when nothing is loaded and the exact return snapshot shape, which is real context beyond the schema. It does not mention permission/auth requirements or error conditions, leaving a small gap for a state-changing tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action, then the constraint, then the alternative, then the return shape, in three compact sentences with no filler. 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?
For a one-optional-parameter tool with an output schema and no annotations, the description covers action, exclusion, alternative, and return structure. Only auth/permission or failure behavior is unaddressed, which is minor given the tool's simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
One optional parameter with 100% schema description coverage, so the schema already explains the 'instance' default behavior. The description adds nothing about the instance parameter, which is the expected baseline when the schema does the heavy lifting.
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 (resume playback) on a specific resource (Kodi remote) and narrows the scope to 'paused playback only'. It explicitly names the sibling it is not (playfile) and the situation where it is a no-op, so an agent can distinguish it from pause/stop/playfile 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?
Gives an explicit when-not ('it cannot start new content (with nothing loaded it is a no-op)') and names the correct alternative for that case ('use playfile to start something'). This is the full when/when-not/alternative triad.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
playfileA
Play one file by path (e.g. a searchmedia result's file): Player.Open auto-selects the audio/video player. Works for any reachable path, in-library or not. A file missing from disk (stale library entry) is reported as an error. Returns the player-state snapshot { "state", "type", "time", "totaltime", "progress", "nowplaying": { "media", "id", "title", "artist", … } }.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path of the file to play — the `file` field of a `searchmedia` result row. Any path Kodi can reach works, in-library or not. | |
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). | |
| fullscreenaudio | No | Audio only: once playback starts, bring Kodi's fullscreen now-playing screen (the `visualisation` window) to the front. Audio playback does not auto-fullscreen the way video does, so without this the player stays behind whatever window is up, showing only the small now-playing strip. Ignored when the open starts video (Kodi already fullscreens that) and a no-op when nothing starts. Note: with no visualisation add-on installed the window renders blank behind the now-playing info. |
Output Schema
| Name | Required | Description |
|---|---|---|
| time | No | Playback position { hours, minutes, seconds, milliseconds }. |
| type | No | The active player kind. |
| audio | No | Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector. |
| state | Yes | Playback state; "stopped" means nothing is loaded. |
| progress | No | Legible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length. |
| subtitle | No | Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector. |
| totaltime | No | The item's duration, same shape as time. |
| nowplaying | No | The loaded media (present whenever something is loaded): { media (song/episode/movie/…; "unknown" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does reasonably well: it discloses auto player selection (Player.Open), broad path reach, and that a missing-on-disk file surfaces as an error. It omits auth/instance-scoping behavior and any side effects on current playback, keeping it 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?
Front-loads the core action and stays in one dense paragraph with little waste. The returned-state enumeration is arguably redundant given an output schema exists, making it slightly longer than needed.
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 purpose, path scope, error behavior, and playback side effect, which is sufficient for a no-annotation mutation-style tool. Since an output schema exists, the embedded state-snapshot description is extra rather than necessary, and instance/auth behavior is left unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning for `file` by tying it to `searchmedia` output paths and the in-library-or-not scope. It says nothing extra about `instance` or `fullscreenaudio`, which remain schema-only.
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 (play) and resource (one file by path), and explicitly frames the input as a `searchmedia` result's `file`, which differentiates it from siblings like `play` and `playfile_with_audio_and_subtitle`. An agent can identify what this does 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 concrete context (use a path from `searchmedia`, any reachable path in-library or not) and notes the stale-entry error case, but never names the alternative sibling `playfile_with_audio_and_subtitle` or states when NOT to use this tool. Clear condition, no explicit exclusion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
playfile_with_audio_and_subtitleA
Play a video file by path AND select its audio track and/or subtitle once it starts — the "when starting playback" partner of set_audio_and_subtitle. "file" is required; "audio" is a stream index and "subtitle" is a stream index or "off", using the "index" values from audio_and_subtitle_info. Give at least one of audio/subtitle (else use playfile). Video only. Returns the player-state snapshot.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path of the video file to play — the `file` field of a `searchmedia` result row, or what `audio_and_subtitle_info` reports. Any path Kodi can reach works, in-library or not. | |
| audio | No | Audio stream index to select — an `index` from `audio_and_subtitle_info`. Omit to leave the audio track unchanged. | |
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). | |
| subtitle | No | Subtitle stream index to show — an `index` from `audio_and_subtitle_info` — or "off" to hide subtitles. Omit to leave the subtitle unchanged ("off" is distinct from omitting it). |
Output Schema
| Name | Required | Description |
|---|---|---|
| time | No | Playback position { hours, minutes, seconds, milliseconds }. |
| type | No | The active player kind. |
| audio | No | Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector. |
| state | Yes | Playback state; "stopped" means nothing is loaded. |
| progress | No | Legible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length. |
| subtitle | No | Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector. |
| totaltime | No | The item's duration, same shape as time. |
| nowplaying | No | The loaded media (present whenever something is loaded): { media (song/episode/movie/…; "unknown" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does well: it discloses the timing behavior ("once it starts"), the argument constraint, the "Video only" limitation, and that it returns a player-state snapshot. It stops short of covering error behavior or what happens to current playback, but the core behavioral profile is present.
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 action, then the constraints and routing in dense em-dash clauses. Every sentence carries information, though the audio/subtitle index wording is slightly repetitive with the 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 4-param tool with full schema coverage and an output schema, the description supplies everything the schema does not: timing, sibling routing, and the required-argument rule. An agent can call it correctly without opening anything else.
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 every parameter including the "off"-vs-omit distinction. The description reinforces the semantics and cross-references audio_and_subtitle_info for index values, but adds little beyond the schema, matching the baseline.
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: play a video file by path while selecting its audio track and/or subtitle. It explicitly positions itself against siblings, calling itself the "when starting playback" partner of set_audio_and_subtitle and routing to playfile when no track selection is needed.
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 usage rule: "Give at least one of audio/subtitle (else use playfile)", and clarifies the timing distinction vs set_audio_and_subtitle. It also states a scope constraint ("Video only"), so an agent knows when not to reach for it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
queueA
Queue an item behind the one now playing, for continuous playback: a searchmedia row's library id (type+id) or a file path; next:true plays it right after the current item. Something must already be playing (start with play/playfile). An item whose file is missing from disk (stale library entry) is refused. Returns the player-state snapshot, unchanged by the add — the current item keeps playing.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Library id of the item to queue — the `songid`/`episodeid`/`movieid` of a `searchmedia` result row, matching `type`. Give exactly one of `id` or `file`. | |
| file | No | Path of the file to queue — the `file` field of a `searchmedia` result row; any path Kodi can reach works. Give exactly one of `id` or `file`. | |
| next | No | When true, insert the item right after the one now playing ("play next") instead of appending to the end of the queue. | |
| type | No | Kind of library id passed in `id` — picks the item key (songid/episodeid/movieid). Required with `id`; not used with `file`. Must match the playing queue: a song joins audio playback, an episode or movie joins video playback. | |
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| time | No | Playback position { hours, minutes, seconds, milliseconds }. |
| type | No | The active player kind. |
| audio | No | Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector. |
| state | Yes | Playback state; "stopped" means nothing is loaded. |
| progress | No | Legible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length. |
| subtitle | No | Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector. |
| totaltime | No | The item's duration, same shape as time. |
| nowplaying | No | The loaded media (present whenever something is loaded): { media (song/episode/movie/…; "unknown" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so: it discloses the prerequisite that playback must be active, the refusal of stale/missing-file entries, and that the return is an unchanged player-state snapshot. These are exactly the behavioral traits an agent needs and none are covered by 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?
Front-loads the core action, then the input forms, constraints, and return value in a compact flow. Dense and slightly packed but nearly 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?
Given an output schema exists, the description needn't detail return values, yet it still notes the snapshot behavior. Combined with preconditions and input guidance, an agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all five parameters including the id/file exclusivity and next semantics. The description reinforces the id-vs-file forms and adds the cross-parameter note that type must match the playing queue, but mostly restates schema content, 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 (queue) and resource (an item behind the one now playing) with the playback scope spelled out. It distinguishes itself from siblings like play/playfile by describing continuous-queue semantics rather than immediate playback.
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 precondition ('Something must already be playing (start with play/playfile)') and names the alternative tools to use first. It also explains that the item can come from a searchmedia row, tying it to the sibling that produces inputs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rpcA
Escape hatch: send a raw JSON-RPC method to Kodi and return its reply unchanged. Disabled unless the target instance has opted in (allow_rpc in the server config, set by hand only).
| Name | Required | Description | Default |
|---|---|---|---|
| method | Yes | JSON-RPC method to invoke verbatim, e.g. "GUI.ActivateWindow" or "Input.Up". Returns Kodi's raw result unchanged. Escape hatch for methods the dedicated tools don't model — disabled unless the target instance has opted in ("allow_rpc" in the server config, set by hand only). No configured instance currently permits it. | |
| params | No | Parameters object passed straight through to the method. Omit for a method that takes none. | |
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses that it passes through raw replies unchanged and is disabled unless configured, providing behavioral context beyond 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 sentences with key information front-loaded, though the second sentence is somewhat lengthy. Efficient overall.
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?
Explains usage, constraints, and behavior. Lacks information about error handling or return format details, but sufficient for this specialized tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% but the description adds clarity: 'method' is verbatim, 'params' passed straight through, 'instance' defaults. Adds value beyond 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 clearly identifies the tool as an 'escape hatch' for sending raw JSON-RPC methods to Kodi, distinguishing it from dedicated tools that model specific methods.
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 states when to use (for methods not modeled by dedicated tools) and conditions (requires opt-in, disabled by default), but lacks explicit comparisons to sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchmediaA
Find playable files by name: music/tv-show/movie, drilled to leaf files with paging (limit/offset) and a total count. For music, title means the ALBUM name; match a song by its own title with the song arg ("play Hey Jude" needs no artist). Find a tv episode by its own name with the episodetitle arg. Movie and tv-show queries can also filter by actor/director. Finds media items only — for people lookups (bands, artists, who is in the library) use contributors. Returns { "type", "total", "returned", "offset", "truncated", "rows": [ { "file", "id", "label", "title", … } ] }.
| Name | Required | Description | Default |
|---|---|---|---|
| song | No | Music only: song title (substring, case-insensitive). Matches songs by their OWN name library-wide — the way to find a track without its album; narrow with artist/title(album)/number. Rows carry no resolved container. | |
| type | Yes | Media kind to search: music | tv-show | movie. | |
| actor | No | movie/tv-show only: cast-member name (substring, case-insensitive). For tv-show it matches episode cast, which includes guest stars; combinable with title. | |
| count | No | When true, return only the total match count (zero rows) — a cheap count. | |
| limit | No | Max leaf rows to return (default 50, max 500). Page with offset. | |
| title | No | Container/title to match (substring, case-insensitive): album for music (a song's own title is the separate `song` arg), show for tv-show, the movie title for movie. tv-show needs title, actor or director; without title the person is matched library-wide and rows carry showtitle. Music without artist resolves the album library-wide. | |
| artist | No | Music only: performer name (substring, case-insensitive). Resolves the artist; music needs artist, title or song. | |
| number | No | Position within the container: track number (music) or episode number (tv-show) — for an episode's title use episodetitle. | |
| offset | No | Number of leaf rows to skip — paginate together with limit. | |
| season | No | tv-show only: season number to narrow the episodes. | |
| director | No | movie/tv-show only: director name (substring, case-insensitive). For tv-show it matches per-episode directors; combinable with title. | |
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). | |
| episodetitle | No | tv-show only: an episode's OWN title (substring, case-insensitive) — the way to find an episode by name. Matched library-wide (rows carry showtitle) unless a show title also narrows it. This is the title, NOT the episode number (use number for that). |
Output Schema
| Name | Required | Description |
|---|---|---|
| rows | Yes | The matching leaf rows, paged. |
| type | Yes | The searched media type, echoed back. |
| total | Yes | Full match count, before any paging. |
| offset | Yes | Rows skipped before this page. |
| resolved | No | The container the query resolved to — { "artist"?|"show"?, "artistid"|"tvshowid" } — when it drilled through one. |
| returned | Yes | Rows in this page. |
| truncated | Yes | Whether matches remain beyond this page. |
| approximate | No | Present (true) when total/paging are app-side estimates (a substring title matched several albums). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden and does so well: it discloses paging via limit/offset, a total count, truncation, the full return envelope, and that song-matched rows carry no resolved container while library-wide person matches carry showtitle. It doesn't state read-only-ness explicitly or discuss result ordering, but the read semantics of 'search' are effectively unambiguous.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in the first clause, followed by parameter routing and the return shape. It is dense but appropriately sized for a 13-parameter tool; the only waste is that the `episodetitle` and `song` explanations restate the schema param descriptions nearly verbatim.
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 13-param search with an output schema, the description covers every meaningful axis: media kinds, paging, the container-vs-item distinction, the sibling escape hatch, and cross-parameter combinations. The return-shape sketch is technically redundant given the output schema, but nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns above it by disambiguating the two most confusable parameters ('For music, title means the ALBUM name; match a song by its own title with the `song` arg') and by mapping actor/director to cast vs per-episode matching. Support is largely duplicative of the schema, which keeps it at 4 rather than 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Find playable files by name: music/tv-show/movie'), names the leaf-file granularity, paging and total count. It also explicitly carves out the sibling boundary: 'Finds media items only — for people lookups ... use `contributors`.' An agent can distinguish this from every sibling 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 routing: `song` for a track by its own title, `title` for the album/show/movie container, `episodetitle` for an episode by name, and `contributors` for people. The 'play Hey Jude needs no artist' example resolves a real ambiguity an agent would otherwise get wrong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_audio_and_subtitleA
Switch the audio track and/or subtitle of the video now playing on the target instance. "audio" is a stream index; "subtitle" is a stream index or "off" to hide subtitles — use the "index" values from audio_and_subtitle_info. Omit an argument to leave that stream unchanged; give at least one. Returns the player-state snapshot.
| Name | Required | Description | Default |
|---|---|---|---|
| audio | No | Audio stream index to select — an `index` from `audio_and_subtitle_info`. Omit to leave the audio track unchanged. | |
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). | |
| subtitle | No | Subtitle stream index to show — an `index` from `audio_and_subtitle_info` — or "off" to hide subtitles. Omit to leave the subtitle unchanged ("off" is distinct from omitting it). |
Output Schema
| Name | Required | Description |
|---|---|---|
| time | No | Playback position { hours, minutes, seconds, milliseconds }. |
| type | No | The active player kind. |
| audio | No | Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector. |
| state | Yes | Playback state; "stopped" means nothing is loaded. |
| progress | No | Legible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length. |
| subtitle | No | Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector. |
| totaltime | No | The item's duration, same shape as time. |
| nowplaying | No | The loaded media (present whenever something is loaded): { media (song/episode/movie/…; "unknown" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It does disclose useful behavior: the tool returns a player-state snapshot, "off" differs from omitting the argument, and at least one argument is required. It does not state that this is a live mutation, that something must be playing, or how errors surface — meaningful gaps for an unannotated mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One dense but tightly ordered paragraph: action, then parameter semantics, then the omit/require rule, then the return. No sentence is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the brief note about returning a player-state snapshot is sufficient. The main missing piece is the precondition that a video must be playing and how failures are reported, which matters for a three-parameter live-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 100%, so the baseline is 3, but the description adds real meaning: it ties both indices to audio_and_subtitle_info, explains the `off` string, and introduces the 'give at least one' constraint that the schema does not express (0 required 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 gives a specific verb+resource: switching the audio track and/or subtitle of the video currently playing on a target instance. It reads clearly against siblings like audio_and_subtitle_info (which supplies the indices) and playfile_with_audio_and_subtitle (which sets streams at playback start), though neither sibling is named.
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 supplies the operative prerequisite — use the `index` values from audio_and_subtitle_info — and states the argument rules (omit to leave unchanged, give at least one). There is no explicit when-not or named alternative for setting streams at playback time, so it stops short of the top mark.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
skipnextA
Press Skip Next (Next track / chapter) on the Kodi remote: advance the active player to the next item in its playlist (or next chapter). A remote keypress, not a player command; with nothing loaded it is a no-op. Returns the player-state snapshot { "state", "type", "time", "totaltime", "progress", "nowplaying": { "media", "id", "title", "artist", … } }.
| Name | Required | Description | Default |
|---|---|---|---|
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| time | No | Playback position { hours, minutes, seconds, milliseconds }. |
| type | No | The active player kind. |
| audio | No | Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector. |
| state | Yes | Playback state; "stopped" means nothing is loaded. |
| progress | No | Legible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length. |
| subtitle | No | Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector. |
| totaltime | No | The item's duration, same shape as time. |
| nowplaying | No | The loaded media (present whenever something is loaded): { media (song/episode/movie/…; "unknown" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does disclose the key edge case (no-op when nothing is loaded) and the remote-keypress semantics, plus what is returned. It does not cover failure modes, permissions, or whether the skip is queued/instantaneous, leaving some behavioral gaps.
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 opening sentence is front-loaded and dense with the essential semantics. The closing enumeration of the player-state snapshot fields is largely redundant given an output schema exists, so it does not fully earn 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 single-optional-parameter remote-key tool with an output schema, the definition covers purpose, edge case, and invocation semantics adequately. Return values need not be described since an output schema exists, though auth/permission expectations are left unstated.
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 optional 'instance' parameter is fully documented in the schema, so the description adds no parameter meaning. This is the baseline case where the schema does the work.
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 ('advance to the next item') and resource (active player's playlist/chapter), and the 'Skip Next' framing plus 'next track/chapter' immediately distinguishes it from the sibling skipprevious and from play/queue. An agent can route to it without ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear context ('A remote keypress, not a player command; with nothing loaded it is a no-op'), which tells the agent this is a remote-control style action rather than a command that loads media. It never explicitly names alternatives such as skipprevious or play, so the when-not guidance stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
skippreviousA
Press Skip Previous (Previous track / chapter) on the Kodi remote: go to the previous item in the playlist (or restart the current item, matching Kodi's own button). A remote keypress, not a player command; with nothing loaded it is a no-op. Returns the player-state snapshot { "state", "type", "time", "totaltime", "progress", "nowplaying": { "media", "id", "title", "artist", … } }.
| Name | Required | Description | Default |
|---|---|---|---|
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| time | No | Playback position { hours, minutes, seconds, milliseconds }. |
| type | No | The active player kind. |
| audio | No | Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector. |
| state | Yes | Playback state; "stopped" means nothing is loaded. |
| progress | No | Legible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length. |
| subtitle | No | Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector. |
| totaltime | No | The item's duration, same shape as time. |
| nowplaying | No | The loaded media (present whenever something is loaded): { media (song/episode/movie/…; "unknown" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does well: it discloses the Kodi-specific restart-vs-previous behavior, the remote-keypress (not API command) semantics, and the no-op case when nothing is loaded. It stops short of mentioning permissions, error conditions, or whether the keypress is queued/async.
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 lead sentence is well front-loaded with the action and target. However, the trailing sentence dumps the full player-state snapshot field list, which duplicates the output schema and consumes a large share of the text without adding selection-relevant value.
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 the description needn't explain return values, though it does anyway. For a single-optional-param remote-control tool, the description covers behavior, edge case (no-op), and effect sufficiently; only permission/error context 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?
There is only one optional parameter ('instance') and schema description coverage is 100%, so the schema already documents it fully. The description adds nothing about instance targeting or default-instance behavior beyond what the schema states, which is the expected baseline here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a concrete verb+resource ('Press Skip Previous ... on the Kodi remote') and clarifies the exact effect: go to the previous playlist item, or restart the current one. It also distinguishes itself from the play/pause/stop family by stating it is 'a remote keypress, not a player command,' though it never names the closest sibling (skipnext) directly.
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 context is implied rather than stated: the agent can infer it is the tool to call when it wants to go backwards, and the no-op condition ('with nothing loaded') is useful. However, no explicit when-to-use guidance or alternative selection (e.g., skipnext vs this tool, or nowplaying to inspect state) is offered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
stopA
Press Stop on the Kodi remote: stop the active player on the target instance and clear the playlist it was playing, so no queued items linger. Returns the player-state snapshot — { "state": "stopped" } after a successful stop.
| Name | Required | Description | Default |
|---|---|---|---|
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| time | No | Playback position { hours, minutes, seconds, milliseconds }. |
| type | No | The active player kind. |
| audio | No | Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector. |
| state | Yes | Playback state; "stopped" means nothing is loaded. |
| progress | No | Legible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length. |
| subtitle | No | Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector. |
| totaltime | No | The item's duration, same shape as time. |
| nowplaying | No | The loaded media (present whenever something is loaded): { media (song/episode/movie/…; "unknown" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose the important non-obvious side effect: the playlist is cleared so queued items don't linger, which matters because stop is more disruptive than pause. It omits permission/auth requirements and error behavior, so it isn't fully transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences, front-loaded with the action and then the side effect. The trailing return-value sentence is largely redundant given the output schema exists, which is the only real waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-optional-param tool with a 100%-covered schema and an output schema, the description covers the action and the destructive playlist-clearing behavior. It does not need to explain return values, and the lack of annotations is partly compensated by the stated side effect.
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?
There is only one optional parameter and schema coverage is 100%, so the schema already documents `instance` and its default. The description adds only the phrase 'target instance', which is marginal beyond the structured field.
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 — stop the active player on the target instance — and names the key side effect (clearing the playing playlist). That effect implicitly distinguishes it from the sibling `pause`, though no sibling is ever named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Press Stop on the Kodi remote' framing gives context for when a user would reach for it, but there is no explicit when-to-use, when-not-to-use, or comparison against `pause`/`dropplaylists`, which are the obvious adjacent choices.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unmuteA
Unmute the target instance's audio output. Returns { "muted", "volume" }.
| Name | Required | Description | Default |
|---|---|---|---|
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| muted | Yes | Whether audio output is muted. |
| volume | Yes | The application volume, 0-100. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It mentions the return format '{ "muted", "volume" }' but does not disclose potential side effects, permissions, or failure conditions.
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?
Extremely concise: one sentence and a return note. No wasted words, front-loaded with the action and resource.
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 (one optional parameter and an output schema), the description covers the core action and return structure. The existence of an output schema compensates for lack of return details in the description. Slightly lacking in error or prerequisite information.
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% for the single parameter 'instance,' which is already described in the input schema. The description adds no additional meaning beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Unmute' and the resource 'target instance's audio output.' It is specific and distinguishes from sibling tools like 'mute' and 'volume' by its opposite action.
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 explicit guidance on when to use this tool versus alternatives like 'mute' or 'volume.' Usage is implied but not directly stated, lacking when-not-to-use or alternative references.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
volumeA
Adjust the target instance's volume by a relative step (in percentage points); step 0 or omitted just reports the current volume. Returns { "muted", "volume", "min", "max" }.
| Name | Required | Description | Default |
|---|---|---|---|
| step | No | Relative volume change in percentage points. 0 or omitted reads the current volume without changing it; positive raises, negative lowers. The result is clamped to the 0-100 range reported as min/max. | |
| instance | No | Target Kodi instance. Omitted uses the default ("(null)"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| max | Yes | Upper volume bound (always 100). |
| min | Yes | Lower volume bound (always 0). |
| muted | Yes | Whether audio output is muted. |
| volume | Yes | The application volume, 0-100. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses relative adjustment, clamping, and return format; no annotations provided, so description carries burden effectively, though permissions or side effects not mentioned.
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 concise sentences plus return format note; front-loaded with purpose, no wasted words.
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?
Complete for a low-parameter tool with output schema; covers adjustment, reading, and return values.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Adds meaning beyond 100% schema coverage: clarifies step as percentage, clamping, instance default, and reading behavior.
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 states the tool adjusts volume by a relative step and reports current volume when step is 0 or omitted, distinguishing it from siblings like mute/unmute.
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 for adjusting or reading volume, but no explicit guidance on when to use vs alternatives like mute, or exclusions.
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.
14 tool updates
- Added
audio_and_subtitle_info - Changed
dropplaylists15 fields changed- removed
Output schema / properties / albumRemoved value: -{ - "description": "Song: the album name.", - "type": "string" -} - removed
Output schema / properties / artistRemoved value: -{ - "description": "Song: the performers, an array of strings.", - "type": "array" -} - added
Output schema / properties / audioAdded value: +{ + "description": "Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.", + "type": "object" +} - removed
Output schema / properties / episodeRemoved value: -{ - "description": "TV episode: episode number.", - "type": "integer" -} - removed
Output schema / properties / fileRemoved value: -{ - "description": "Path of the playing item.", - "type": "string" -} - removed
Output schema / properties / idRemoved value: -{ - "description": "Library id of the playing item; -1 when off-library.", - "type": "integer" -} - removed
Output schema / properties / labelRemoved value: -{ - "description": "Kodi's display label for the item.", - "type": "string" -} - removed
Output schema / properties / mediaRemoved value: -{ - "description": "Real media type (song/episode/movie/musicvideo/…); \"unknown\" for an off-library file.", - "type": "string" -} - added
Output schema / properties / nowplayingAdded value: +{ + "description": "The loaded media (present whenever something is loaded): { media (song/episode/movie/…; \"unknown\" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }.", + "type": "object" +} - added
Output schema / properties / progressAdded value: +{ + "description": "Legible position derived from time/totaltime, \"elapsed / total (NN%)\" e.g. \"15:38 / 46:40 (33%)\"; absent for live streams with no fixed length.", + "type": "string" +} - removed
Output schema / properties / seasonRemoved value: -{ - "description": "TV episode: season number.", - "type": "integer" -} - removed
Output schema / properties / showtitleRemoved value: -{ - "description": "TV episode: the show's name.", - "type": "string" -} - added
Output schema / properties / subtitleAdded value: +{ + "description": "Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector.", + "type": "object" +} - removed
Output schema / properties / titleRemoved value: -{ - "description": "The item's title (may be empty).", - "type": "string" -} - removed
Output schema / properties / trackRemoved value: -{ - "description": "Song: track number on the album.", - "type": "integer" -}
- Added
notify - Changed
nowplaying15 fields changed- removed
Output schema / properties / albumRemoved value: -{ - "description": "Song: the album name.", - "type": "string" -} - removed
Output schema / properties / artistRemoved value: -{ - "description": "Song: the performers, an array of strings.", - "type": "array" -} - added
Output schema / properties / audioAdded value: +{ + "description": "Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.", + "type": "object" +} - removed
Output schema / properties / episodeRemoved value: -{ - "description": "TV episode: episode number.", - "type": "integer" -} - removed
Output schema / properties / fileRemoved value: -{ - "description": "Path of the playing item.", - "type": "string" -} - removed
Output schema / properties / idRemoved value: -{ - "description": "Library id of the playing item; -1 when off-library.", - "type": "integer" -} - removed
Output schema / properties / labelRemoved value: -{ - "description": "Kodi's display label for the item.", - "type": "string" -} - removed
Output schema / properties / mediaRemoved value: -{ - "description": "Real media type (song/episode/movie/musicvideo/…); \"unknown\" for an off-library file.", - "type": "string" -} - added
Output schema / properties / nowplayingAdded value: +{ + "description": "The loaded media (present whenever something is loaded): { media (song/episode/movie/…; \"unknown\" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }.", + "type": "object" +} - added
Output schema / properties / progressAdded value: +{ + "description": "Legible position derived from time/totaltime, \"elapsed / total (NN%)\" e.g. \"15:38 / 46:40 (33%)\"; absent for live streams with no fixed length.", + "type": "string" +} - removed
Output schema / properties / seasonRemoved value: -{ - "description": "TV episode: season number.", - "type": "integer" -} - removed
Output schema / properties / showtitleRemoved value: -{ - "description": "TV episode: the show's name.", - "type": "string" -} - added
Output schema / properties / subtitleAdded value: +{ + "description": "Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector.", + "type": "object" +} - removed
Output schema / properties / titleRemoved value: -{ - "description": "The item's title (may be empty).", - "type": "string" -} - removed
Output schema / properties / trackRemoved value: -{ - "description": "Song: track number on the album.", - "type": "integer" -}
- Changed
pause15 fields changed- removed
Output schema / properties / albumRemoved value: -{ - "description": "Song: the album name.", - "type": "string" -} - removed
Output schema / properties / artistRemoved value: -{ - "description": "Song: the performers, an array of strings.", - "type": "array" -} - added
Output schema / properties / audioAdded value: +{ + "description": "Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.", + "type": "object" +} - removed
Output schema / properties / episodeRemoved value: -{ - "description": "TV episode: episode number.", - "type": "integer" -} - removed
Output schema / properties / fileRemoved value: -{ - "description": "Path of the playing item.", - "type": "string" -} - removed
Output schema / properties / idRemoved value: -{ - "description": "Library id of the playing item; -1 when off-library.", - "type": "integer" -} - removed
Output schema / properties / labelRemoved value: -{ - "description": "Kodi's display label for the item.", - "type": "string" -} - removed
Output schema / properties / mediaRemoved value: -{ - "description": "Real media type (song/episode/movie/musicvideo/…); \"unknown\" for an off-library file.", - "type": "string" -} - added
Output schema / properties / nowplayingAdded value: +{ + "description": "The loaded media (present whenever something is loaded): { media (song/episode/movie/…; \"unknown\" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }.", + "type": "object" +} - added
Output schema / properties / progressAdded value: +{ + "description": "Legible position derived from time/totaltime, \"elapsed / total (NN%)\" e.g. \"15:38 / 46:40 (33%)\"; absent for live streams with no fixed length.", + "type": "string" +} - removed
Output schema / properties / seasonRemoved value: -{ - "description": "TV episode: season number.", - "type": "integer" -} - removed
Output schema / properties / showtitleRemoved value: -{ - "description": "TV episode: the show's name.", - "type": "string" -} - added
Output schema / properties / subtitleAdded value: +{ + "description": "Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector.", + "type": "object" +} - removed
Output schema / properties / titleRemoved value: -{ - "description": "The item's title (may be empty).", - "type": "string" -} - removed
Output schema / properties / trackRemoved value: -{ - "description": "Song: track number on the album.", - "type": "integer" -}
- Changed
play15 fields changed- removed
Output schema / properties / albumRemoved value: -{ - "description": "Song: the album name.", - "type": "string" -} - removed
Output schema / properties / artistRemoved value: -{ - "description": "Song: the performers, an array of strings.", - "type": "array" -} - added
Output schema / properties / audioAdded value: +{ + "description": "Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.", + "type": "object" +} - removed
Output schema / properties / episodeRemoved value: -{ - "description": "TV episode: episode number.", - "type": "integer" -} - removed
Output schema / properties / fileRemoved value: -{ - "description": "Path of the playing item.", - "type": "string" -} - removed
Output schema / properties / idRemoved value: -{ - "description": "Library id of the playing item; -1 when off-library.", - "type": "integer" -} - removed
Output schema / properties / labelRemoved value: -{ - "description": "Kodi's display label for the item.", - "type": "string" -} - removed
Output schema / properties / mediaRemoved value: -{ - "description": "Real media type (song/episode/movie/musicvideo/…); \"unknown\" for an off-library file.", - "type": "string" -} - added
Output schema / properties / nowplayingAdded value: +{ + "description": "The loaded media (present whenever something is loaded): { media (song/episode/movie/…; \"unknown\" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }.", + "type": "object" +} - added
Output schema / properties / progressAdded value: +{ + "description": "Legible position derived from time/totaltime, \"elapsed / total (NN%)\" e.g. \"15:38 / 46:40 (33%)\"; absent for live streams with no fixed length.", + "type": "string" +} - removed
Output schema / properties / seasonRemoved value: -{ - "description": "TV episode: season number.", - "type": "integer" -} - removed
Output schema / properties / showtitleRemoved value: -{ - "description": "TV episode: the show's name.", - "type": "string" -} - added
Output schema / properties / subtitleAdded value: +{ + "description": "Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector.", + "type": "object" +} - removed
Output schema / properties / titleRemoved value: -{ - "description": "The item's title (may be empty).", - "type": "string" -} - removed
Output schema / properties / trackRemoved value: -{ - "description": "Song: track number on the album.", - "type": "integer" -}
- Changed
playfile16 fields changed- added
Input schema / properties / fullscreenaudioAdded value: +{ + "description": "Audio only: once playback starts, bring Kodi's fullscreen now-playing screen (the `visualisation` window) to the front. Audio playback does not auto-fullscreen the way video does, so without this the player stays behind whatever window is up, showing only the small now-playing strip. Ignored when the open starts video (Kodi already fullscreens that) and a no-op when nothing starts. Note: with no visualisation add-on installed the window renders blank behind the now-playing info.", + "type": "boolean" +} - removed
Output schema / properties / albumRemoved value: -{ - "description": "Song: the album name.", - "type": "string" -} - removed
Output schema / properties / artistRemoved value: -{ - "description": "Song: the performers, an array of strings.", - "type": "array" -} - added
Output schema / properties / audioAdded value: +{ + "description": "Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.", + "type": "object" +} - removed
Output schema / properties / episodeRemoved value: -{ - "description": "TV episode: episode number.", - "type": "integer" -} - removed
Output schema / properties / fileRemoved value: -{ - "description": "Path of the playing item.", - "type": "string" -} - removed
Output schema / properties / idRemoved value: -{ - "description": "Library id of the playing item; -1 when off-library.", - "type": "integer" -} - removed
Output schema / properties / labelRemoved value: -{ - "description": "Kodi's display label for the item.", - "type": "string" -} - removed
Output schema / properties / mediaRemoved value: -{ - "description": "Real media type (song/episode/movie/musicvideo/…); \"unknown\" for an off-library file.", - "type": "string" -} - added
Output schema / properties / nowplayingAdded value: +{ + "description": "The loaded media (present whenever something is loaded): { media (song/episode/movie/…; \"unknown\" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }.", + "type": "object" +} - added
Output schema / properties / progressAdded value: +{ + "description": "Legible position derived from time/totaltime, \"elapsed / total (NN%)\" e.g. \"15:38 / 46:40 (33%)\"; absent for live streams with no fixed length.", + "type": "string" +} - removed
Output schema / properties / seasonRemoved value: -{ - "description": "TV episode: season number.", - "type": "integer" -} - removed
Output schema / properties / showtitleRemoved value: -{ - "description": "TV episode: the show's name.", - "type": "string" -} - added
Output schema / properties / subtitleAdded value: +{ + "description": "Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector.", + "type": "object" +} - removed
Output schema / properties / titleRemoved value: -{ - "description": "The item's title (may be empty).", - "type": "string" -} - removed
Output schema / properties / trackRemoved value: -{ - "description": "Song: track number on the album.", - "type": "integer" -}
- Added
playfile_with_audio_and_subtitle - Changed
queue15 fields changed- removed
Output schema / properties / albumRemoved value: -{ - "description": "Song: the album name.", - "type": "string" -} - removed
Output schema / properties / artistRemoved value: -{ - "description": "Song: the performers, an array of strings.", - "type": "array" -} - added
Output schema / properties / audioAdded value: +{ + "description": "Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.", + "type": "object" +} - removed
Output schema / properties / episodeRemoved value: -{ - "description": "TV episode: episode number.", - "type": "integer" -} - removed
Output schema / properties / fileRemoved value: -{ - "description": "Path of the playing item.", - "type": "string" -} - removed
Output schema / properties / idRemoved value: -{ - "description": "Library id of the playing item; -1 when off-library.", - "type": "integer" -} - removed
Output schema / properties / labelRemoved value: -{ - "description": "Kodi's display label for the item.", - "type": "string" -} - removed
Output schema / properties / mediaRemoved value: -{ - "description": "Real media type (song/episode/movie/musicvideo/…); \"unknown\" for an off-library file.", - "type": "string" -} - added
Output schema / properties / nowplayingAdded value: +{ + "description": "The loaded media (present whenever something is loaded): { media (song/episode/movie/…; \"unknown\" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }.", + "type": "object" +} - added
Output schema / properties / progressAdded value: +{ + "description": "Legible position derived from time/totaltime, \"elapsed / total (NN%)\" e.g. \"15:38 / 46:40 (33%)\"; absent for live streams with no fixed length.", + "type": "string" +} - removed
Output schema / properties / seasonRemoved value: -{ - "description": "TV episode: season number.", - "type": "integer" -} - removed
Output schema / properties / showtitleRemoved value: -{ - "description": "TV episode: the show's name.", - "type": "string" -} - added
Output schema / properties / subtitleAdded value: +{ + "description": "Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector.", + "type": "object" +} - removed
Output schema / properties / titleRemoved value: -{ - "description": "The item's title (may be empty).", - "type": "string" -} - removed
Output schema / properties / trackRemoved value: -{ - "description": "Song: track number on the album.", - "type": "integer" -}
- Changed
searchmedia5 fields changed- changed
Input schema / properties / artist / descriptionPrevious value: -"Music only: performer name (substring, case-insensitive). Resolves the artist; music needs artist or title."New value: +"Music only: performer name (substring, case-insensitive). Resolves the artist; music needs artist, title or song." - added
Input schema / properties / episodetitleAdded value: +{ + "description": "tv-show only: an episode's OWN title (substring, case-insensitive) — the way to find an episode by name. Matched library-wide (rows carry showtitle) unless a show title also narrows it. This is the title, NOT the episode number (use number for that).", + "type": "string" +} - changed
Input schema / properties / number / descriptionPrevious value: -"Position within the container: track number (music) or episode number (tv-show)."New value: +"Position within the container: track number (music) or episode number (tv-show) — for an episode's title use episodetitle." - added
Input schema / properties / songAdded value: +{ + "description": "Music only: song title (substring, case-insensitive). Matches songs by their OWN name library-wide — the way to find a track without its album; narrow with artist/title(album)/number. Rows carry no resolved container.", + "type": "string" +} - changed
Input schema / properties / title / descriptionPrevious value: -"Container/title to match (substring, case-insensitive): album for music, show for tv-show, the movie title for movie. tv-show needs title, actor or director; without title the person is matched library-wide and rows carry showtitle. Music without artist resolves the album library-wide."New value: +"Container/title to match (substring, case-insensitive): album for music (a song's own title is the separate `song` arg), show for tv-show, the movie title for movie. tv-show needs title, actor or director; without title the person is matched library-wide and rows carry showtitle. Music without artist resolves the album library-wide."
- Added
set_audio_and_subtitle - Added
skipnext - Added
skipprevious - Changed
stop15 fields changed- removed
Output schema / properties / albumRemoved value: -{ - "description": "Song: the album name.", - "type": "string" -} - removed
Output schema / properties / artistRemoved value: -{ - "description": "Song: the performers, an array of strings.", - "type": "array" -} - added
Output schema / properties / audioAdded value: +{ + "description": "Audio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.", + "type": "object" +} - removed
Output schema / properties / episodeRemoved value: -{ - "description": "TV episode: episode number.", - "type": "integer" -} - removed
Output schema / properties / fileRemoved value: -{ - "description": "Path of the playing item.", - "type": "string" -} - removed
Output schema / properties / idRemoved value: -{ - "description": "Library id of the playing item; -1 when off-library.", - "type": "integer" -} - removed
Output schema / properties / labelRemoved value: -{ - "description": "Kodi's display label for the item.", - "type": "string" -} - removed
Output schema / properties / mediaRemoved value: -{ - "description": "Real media type (song/episode/movie/musicvideo/…); \"unknown\" for an off-library file.", - "type": "string" -} - added
Output schema / properties / nowplayingAdded value: +{ + "description": "The loaded media (present whenever something is loaded): { media (song/episode/movie/…; \"unknown\" off-library), id (library id, -1 off-library), file, label, title; and where they apply showtitle/season/episode (TV), album/artist/track (song) }.", + "type": "object" +} - added
Output schema / properties / progressAdded value: +{ + "description": "Legible position derived from time/totaltime, \"elapsed / total (NN%)\" e.g. \"15:38 / 46:40 (33%)\"; absent for live streams with no fixed length.", + "type": "string" +} - removed
Output schema / properties / seasonRemoved value: -{ - "description": "TV episode: season number.", - "type": "integer" -} - removed
Output schema / properties / showtitleRemoved value: -{ - "description": "TV episode: the show's name.", - "type": "string" -} - added
Output schema / properties / subtitleAdded value: +{ + "description": "Subtitles of the playing video (video only, present only when any exist): { count, enabled, current: { index, language } }. `current` is present only while a subtitle is shown; `index` is the set_audio_and_subtitle subtitle selector.", + "type": "object" +} - removed
Output schema / properties / titleRemoved value: -{ - "description": "The item's title (may be empty).", - "type": "string" -} - removed
Output schema / properties / trackRemoved value: -{ - "description": "Song: track number on the album.", - "type": "integer" -}
16 tool updates
v0.1.0- First observed
contributors - First observed
dropplaylists - First observed
getplaylist - First observed
history - First observed
instances - First observed
mute - First observed
nowplaying - First observed
pause - First observed
play - First observed
playfile - First observed
queue - First observed
rpc - First observed
searchmedia - First observed
stop - First observed
unmute - First observed
volume
TDQS
Scored across 22 tools
Most tools target a distinct resource+action (play/pause/stop, skipnext/skipprevious, mute/unmute/volume) and are clearly separable. The only real overlap is the audio/subtitle cluster: playfile vs playfile_with_audio_and_subtitle, and set_audio_and_subtitle vs the others, but the descriptions explicitly state when to use each, so ambiguity is low.
Conventions are mixed: bare verbs (play, pause, stop, queue, notify), concatenated lowercase (nowplaying, skipnext, searchmedia, getplaylist, dropplaylists), and snake_case (audio_and_subtitle_info, set_audio_and_subtitle, playfile_with_audio_and_subtitle). All lowercase keeps it readable, but there is no single predictable pattern.
22 tools is on the heavier side for a media-center controller, but the domain (playback, search, queueing, audio/subtitle, volume, history, config, raw RPC) is broad and each tool is distinct. Mute/unmute could be a single toggle, but overall the set is justifiable.
Coverage is strong across playback control, media/people search, queue read/drop, audio-subtitle selection, volume/mute, notifications, history, instance config, and a raw JSON-RPC escape hatch. Minor gaps exist (no seek/position control, no individual queue-item removal, no library scan/update), but core workflows are complete.
Maintenance
Related MCP Connectors
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
MCP server for Argo RPG Platform — connects AI assistants to campaign data via OAuth2
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to control Unreal E…
Related MCP Servers
- FlicenseAqualityDmaintenanceAn MCP server that enables AI assistants to control TVs on a local network through natural language commands. It currently supports Roku devices, allowing users to launch apps, manage playback, and navigate menus.5-
- AlicenseAqualityCmaintenanceControl mpv media player through AI conversation. Play music and video, manage playlists — all via natural language. Works with opencode and any MCP-compatible AI tool.164 npmMIT
- AlicenseAqualityDmaintenanceMCP server that enables natural language control of internet radio from Claude Code, with access to 30,000+ global stations, auto-playback via mpv, and a real-time status line with audio spectrum visualization.7MIT
- AlicenseAqualityDmaintenanceMCP server for controlling the mpv media player, enabling playback control, music library browsing, YouTube streaming and downloading, and metadata editing from within an MCP client.1720 npm1MIT