Skip to main content
Glama

mcp-kodi

License: GPLv3 Language: C Sponsor Last commit

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 rpc escape 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

play

Press Play on the remote — resume or begin playback on the target box.

pause

Press Pause — pause the active player.

stop

Press Stop — stop the active player and clear the playlist it was consuming, so no queued items linger.

skipnext

Press Skip Next — advance to the next track/chapter in the active playlist.

skipprevious

Press Skip Previous — go to the previous track/chapter (or restart the current item).

volume

Adjust the volume by a relative signed step (percentage points); step 0/omitted just reads. Never an absolute level, so the assistant can't blast or silence the box by guessing. Returns volume, mute state, and the 0–100 bounds.

mute

Mute the box's audio output.

unmute

Unmute the box's audio output.

nowplaying

Report what is playing without changing anything — also a reachability + state probe.

notify

Show a notification toast on the box's screen — title + message, with an optional icon (info/warning/error or any image path/URL) and display time. Doesn't touch playback.

Search & discovery

Tool

What it does

searchmedia

Find playable leaf files by name across music / tv-show / movie, with paging (limit/offset) and a total count. Music title matches the album; the song arg matches a track by its own title library-wide ("play Hey Jude" needs no artist), narrowable by artist/title/number. For tv, title matches the show; the episodetitle arg finds an episode by its own title library-wide (narrowable by a show title). Movie/tv-show queries can also filter by actor/director. Resolves the library by name, so the assistant acts by title, not numeric id. Media items only — people lookups live in contributors.

contributors

Find or list people — bands, solo artists, composers, actors, directors — by optional name substring and/or type. Each row says where the name yields hits (albums/songs/movies/tvshows); feed the exact name back into searchmedia to drill.

audio_and_subtitle_info

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 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.

set_audio_and_subtitle

Switch the audio track and/or subtitle of the video now playing, by the index from audio_and_subtitle_info. audio is a stream index; subtitle is a stream index or "off" to hide subtitles. Omit an argument to leave that stream unchanged; give at least one. Video only. Returns the player-state snapshot.

Playback & queue

Tool

What it does

playfile

Play one file by path (typically a searchmedia result's file). Kodi 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.

queue

Append an item behind the one now playing (a searchmedia library id type+id, or a file path); next: true inserts it right after the current item. Something must already be playing. A file missing from disk is refused.

getplaylist

Read a queue without changing it — the active player's playlist, or a named one (audio/video/picture), plus the now-playing position. Read-only; an empty queue is an empty list.

dropplaylists

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 getplaylist first if the content matters.

Bookkeeping & escape hatch

Tool

What it does

history

List recently played items from the local playback log, written as a side effect of every playback-affecting call. Optional ISO-8601 since/until window plus app-side filters — media, kind, artist, free-text match, exact id — all AND-combined, with limit/offset/order paging and a count-only mode. Reads only the local log — no Kodi call, so it works even when no box is reachable. Omitted instance returns all boxes.

instances

Read or modify the server's own instance config (get/set/remove). Makes no Kodi call; never returns stored passwords. Also reports the server's build ID (build), the same one shown in serverInfo.version and the session instructions, so an assistant can spot a stale binary.

rpc

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. auth is write-only — the instances tool 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_rpc is not a field the instances tool can write, so the assistant can never grant itself the unrestricted rpc passthrough. 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 (hall, bedroom, …).

default

The key used when a tool omits instance.

name

Optional human-readable label, surfaced in the tool schema.

host

host[:port] of the box (or the proxy in front of it).

auth

HTTP Basic credentials as user:pass. Write-only — never returned by instances get.

scheme

http or https (default https).

insecure

true accepts a self-signed cert — the JSON equivalent of curl -k.

allow_rpc

true opts this box into the rpc escape hatch. Hand-edit only.

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 set allow_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-kodi

Claude 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.json stores Kodi passwords in plaintext, mode 0600. Protect it like any other credential file.

  • insecure: true disables TLS certificate verification for that box. It is the right choice behind Caddy's tls internal self-signed cert, but means the connection is encrypted, not authenticated against a CA — keep the proxy on a trusted network.

  • The rpc escape hatch can invoke any JSON-RPC method (including destructive ones like System.Shutdown). It stays off until you deliberately set allow_rpc: true for a specific box. Enable it only where you trust the assistant to operate unconstrained.


License

Copyright © 2026 Laszlo Pere &lt;laszlopere@gmail.com&gt;. 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 tools
audio_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.

NameRequiredDescriptionDefault
idNoLibrary id of the item to inspect — the `movieid`/`episodeid` of a `searchmedia` result row, matching `type`. Give exactly one of `id` or `file`.
fileNoPath 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`.
typeNoKind 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.
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").

Output Schema

NameRequiredDescription
fileYesThe resolved file path of the inspected item.
audioYesEmbedded audio tracks, in stream order.
videoYesVideo streams, in stream order.
subtitleYesEmbedded subtitle tracks, in stream order.

TDQS

A4.6/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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" }.

NameRequiredDescriptionDefault
nameNoPerson name to look for (substring, case-insensitive): a band, solo artist, composer, actor, or director. Omit to list everyone (of `type` when given).
typeNoContributor 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.
countNoWhen true, return only the total match count (zero rows).
limitNoMax rows to return (default 50, max 500). Page with offset.
offsetNoNumber of rows to skip — paginate together with limit.
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").

Output Schema

NameRequiredDescription
rowsYesThe matching people, merged and sorted by name.
totalYesFull match count, before any paging.
offsetYesRows skipped before this page.
returnedYesRows in this page.
truncatedYesWhether matches remain beyond this page.

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

NameRequiredDescriptionDefault
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").

Output Schema

NameRequiredDescription
timeNoPlayback position { hours, minutes, seconds, milliseconds }.
typeNoThe active player kind.
audioNoAudio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.
stateYesPlayback state; "stopped" means nothing is loaded.
progressNoLegible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length.
subtitleNoSubtitles 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.
totaltimeNoThe item's duration, same shape as time.
nowplayingNoThe 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

A4.5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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" } ] }.

NameRequiredDescriptionDefault
typeNoWhich 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.
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").

Output Schema

NameRequiredDescription
typeNoThe playlist read, when one was resolved.
itemsYesThe queued items, in playback order.
totalYesNumber of queued items.
positionNoIndex of the now-playing item — present only when the playlist read is the active player's own.

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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", … } ] }.

NameRequiredDescriptionDefault
idNoExact 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.
kindNoKeep only entries of this broad kind: audio or video — e.g. "what music did I play".
countNoWhen true, return only the total match count (zero entries) — a cheap "how many times / how much did X play".
limitNoMax entries to return (default 50, max 1000). When more match, the reply sets "truncated": true — page the rest with offset.
matchNoFree-text substring (case-insensitive) over an entry's human fields — title, album, show, label and artist — to narrow the log without knowing ids.
mediaNoKeep only entries of this media kind (song/episode/movie/musicvideo/picture/channel) — e.g. "movies only".
orderNoResult order: "newest" first (default) or "oldest" first to replay a session in the order it happened.
sinceNoOnly 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.
untilNoOnly entries at or before this ISO-8601 time. Omitted = up to now.
artistNoKeep 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.
offsetNoNumber of matching entries to skip before this page — paginate together with limit, keeping the same order.
instanceNoRestrict 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

NameRequiredDescription
sinceNoThe window's lower bound, echoed when one was given.
totalYesFull match count, before any paging.
untilNoThe window's upper bound, echoed when one was given.
offsetYesRows skipped before this page.
entriesYesThe matching history records.
instanceNoThe instance filter, echoed when one was given.
returnedYesRows in this page.
truncatedYesWhether matches remain beyond this page.

TDQS

A5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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", … } ] }.

NameRequiredDescriptionDefault
keyNoInstance key — the short id tools target. Required for "set" and "remove".
authNoHTTP Basic credentials as "user:pass" ("set"). Write-only: never returned by "get".
hostNoKodi host as "host[:port]" ("set").
nameNoHuman-readable display label ("set").
actionYesOperation: "get" lists configured instances, "set" creates/updates one, "remove" deletes one.
schemeNoURL scheme, "http" or "https" ("set"; default "https").
defaultNoWhen true on "set", make this instance the default.
insecureNoAccept a self-signed TLS certificate, like curl -k ("set").

Output Schema

NameRequiredDescription
defaultYesKey of the default instance, or null when none is configured.
instancesYesThe configured instances, in sorted key order.

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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" }.

NameRequiredDescriptionDefault
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").

Output Schema

NameRequiredDescription
mutedYesWhether audio output is muted.
volumeYesThe application volume, 0-100.

TDQS

A3.8/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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"? }.

NameRequiredDescriptionDefault
imageNoIcon 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.
titleYesNotification title — the bold heading of the toast.
messageYesNotification body text shown beneath the title.
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").
displaytimeNoHow 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

NameRequiredDescription
imageNoThe icon keyword or image path that was used, present only when one was supplied.
shownYesAlways true — the notification was handed to Kodi.
titleYesThe title that was shown.
messageYesThe message that was shown.
displaytimeYesThe display time in milliseconds — the requested value, or 5000 (Kodi's default) when none was given.

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

NameRequiredDescriptionDefault
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").

Output Schema

NameRequiredDescription
timeNoPlayback position { hours, minutes, seconds, milliseconds }.
typeNoThe active player kind.
audioNoAudio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.
stateYesPlayback state; "stopped" means nothing is loaded.
progressNoLegible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length.
subtitleNoSubtitles 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.
totaltimeNoThe item's duration, same shape as time.
nowplayingNoThe 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

A4/5.0
Behavior4/5

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.

Conciseness3/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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", … } }.

NameRequiredDescriptionDefault
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").

Output Schema

NameRequiredDescription
timeNoPlayback position { hours, minutes, seconds, milliseconds }.
typeNoThe active player kind.
audioNoAudio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.
stateYesPlayback state; "stopped" means nothing is loaded.
progressNoLegible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length.
subtitleNoSubtitles 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.
totaltimeNoThe item's duration, same shape as time.
nowplayingNoThe 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

B3.2/5.0
Behavior3/5

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.

Conciseness4/5

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.

Completeness3/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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", … } }.

NameRequiredDescriptionDefault
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").

Output Schema

NameRequiredDescription
timeNoPlayback position { hours, minutes, seconds, milliseconds }.
typeNoThe active player kind.
audioNoAudio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.
stateYesPlayback state; "stopped" means nothing is loaded.
progressNoLegible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length.
subtitleNoSubtitles 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.
totaltimeNoThe item's duration, same shape as time.
nowplayingNoThe 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

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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", … } }.

NameRequiredDescriptionDefault
fileYesPath of the file to play — the `file` field of a `searchmedia` result row. Any path Kodi can reach works, in-library or not.
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").
fullscreenaudioNoAudio 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

NameRequiredDescription
timeNoPlayback position { hours, minutes, seconds, milliseconds }.
typeNoThe active player kind.
audioNoAudio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.
stateYesPlayback state; "stopped" means nothing is loaded.
progressNoLegible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length.
subtitleNoSubtitles 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.
totaltimeNoThe item's duration, same shape as time.
nowplayingNoThe 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

A4.3/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

NameRequiredDescriptionDefault
fileYesPath 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.
audioNoAudio stream index to select — an `index` from `audio_and_subtitle_info`. Omit to leave the audio track unchanged.
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").
subtitleNoSubtitle 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

NameRequiredDescription
timeNoPlayback position { hours, minutes, seconds, milliseconds }.
typeNoThe active player kind.
audioNoAudio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.
stateYesPlayback state; "stopped" means nothing is loaded.
progressNoLegible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length.
subtitleNoSubtitles 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.
totaltimeNoThe item's duration, same shape as time.
nowplayingNoThe 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

A4.4/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

NameRequiredDescriptionDefault
idNoLibrary id of the item to queue — the `songid`/`episodeid`/`movieid` of a `searchmedia` result row, matching `type`. Give exactly one of `id` or `file`.
fileNoPath 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`.
nextNoWhen true, insert the item right after the one now playing ("play next") instead of appending to the end of the queue.
typeNoKind 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.
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").

Output Schema

NameRequiredDescription
timeNoPlayback position { hours, minutes, seconds, milliseconds }.
typeNoThe active player kind.
audioNoAudio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.
stateYesPlayback state; "stopped" means nothing is loaded.
progressNoLegible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length.
subtitleNoSubtitles 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.
totaltimeNoThe item's duration, same shape as time.
nowplayingNoThe 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

A4.6/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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).

NameRequiredDescriptionDefault
methodYesJSON-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.
paramsNoParameters object passed straight through to the method. Omit for a method that takes none.
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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", … } ] }.

NameRequiredDescriptionDefault
songNoMusic 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.
typeYesMedia kind to search: music | tv-show | movie.
actorNomovie/tv-show only: cast-member name (substring, case-insensitive). For tv-show it matches episode cast, which includes guest stars; combinable with title.
countNoWhen true, return only the total match count (zero rows) — a cheap count.
limitNoMax leaf rows to return (default 50, max 500). Page with offset.
titleNoContainer/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.
artistNoMusic only: performer name (substring, case-insensitive). Resolves the artist; music needs artist, title or song.
numberNoPosition within the container: track number (music) or episode number (tv-show) — for an episode's title use episodetitle.
offsetNoNumber of leaf rows to skip — paginate together with limit.
seasonNotv-show only: season number to narrow the episodes.
directorNomovie/tv-show only: director name (substring, case-insensitive). For tv-show it matches per-episode directors; combinable with title.
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").
episodetitleNotv-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

NameRequiredDescription
rowsYesThe matching leaf rows, paged.
typeYesThe searched media type, echoed back.
totalYesFull match count, before any paging.
offsetYesRows skipped before this page.
resolvedNoThe container the query resolved to — { "artist"?|"show"?, "artistid"|"tvshowid" } — when it drilled through one.
returnedYesRows in this page.
truncatedYesWhether matches remain beyond this page.
approximateNoPresent (true) when total/paging are app-side estimates (a substring title matched several albums).

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

NameRequiredDescriptionDefault
audioNoAudio stream index to select — an `index` from `audio_and_subtitle_info`. Omit to leave the audio track unchanged.
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").
subtitleNoSubtitle 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

NameRequiredDescription
timeNoPlayback position { hours, minutes, seconds, milliseconds }.
typeNoThe active player kind.
audioNoAudio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.
stateYesPlayback state; "stopped" means nothing is loaded.
progressNoLegible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length.
subtitleNoSubtitles 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.
totaltimeNoThe item's duration, same shape as time.
nowplayingNoThe 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

A3.9/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines4/5

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", … } }.

NameRequiredDescriptionDefault
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").

Output Schema

NameRequiredDescription
timeNoPlayback position { hours, minutes, seconds, milliseconds }.
typeNoThe active player kind.
audioNoAudio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.
stateYesPlayback state; "stopped" means nothing is loaded.
progressNoLegible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length.
subtitleNoSubtitles 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.
totaltimeNoThe item's duration, same shape as time.
nowplayingNoThe 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

A4.1/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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", … } }.

NameRequiredDescriptionDefault
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").

Output Schema

NameRequiredDescription
timeNoPlayback position { hours, minutes, seconds, milliseconds }.
typeNoThe active player kind.
audioNoAudio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.
stateYesPlayback state; "stopped" means nothing is loaded.
progressNoLegible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length.
subtitleNoSubtitles 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.
totaltimeNoThe item's duration, same shape as time.
nowplayingNoThe 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

A3.6/5.0
Behavior4/5

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.

Conciseness3/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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.

NameRequiredDescriptionDefault
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").

Output Schema

NameRequiredDescription
timeNoPlayback position { hours, minutes, seconds, milliseconds }.
typeNoThe active player kind.
audioNoAudio tracks of the playing video (video only): { count, current: { index, language, codec, channels } }. `index` is the set_audio_and_subtitle audio selector.
stateYesPlayback state; "stopped" means nothing is loaded.
progressNoLegible position derived from time/totaltime, "elapsed / total (NN%)" e.g. "15:38 / 46:40 (33%)"; absent for live streams with no fixed length.
subtitleNoSubtitles 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.
totaltimeNoThe item's duration, same shape as time.
nowplayingNoThe 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

A3.5/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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" }.

NameRequiredDescriptionDefault
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").

Output Schema

NameRequiredDescription
mutedYesWhether audio output is muted.
volumeYesThe application volume, 0-100.

TDQS

A3.8/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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" }.

NameRequiredDescriptionDefault
stepNoRelative 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.
instanceNoTarget Kodi instance. Omitted uses the default ("(null)").

Output Schema

NameRequiredDescription
maxYesUpper volume bound (always 100).
minYesLower volume bound (always 0).
mutedYesWhether audio output is muted.
volumeYesThe application volume, 0-100.

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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.

  1. 14 tool updates
    • Addedaudio_and_subtitle_info
    • Changeddropplaylists15 fields changed
      • removedOutput schema / properties / album
        Removed value: -{
        -  "description": "Song: the album name.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / artist
        Removed value: -{
        -  "description": "Song: the performers, an array of strings.",
        -  "type": "array"
        -}
      • addedOutput schema / properties / audio
        Added 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"
        +}
      • removedOutput schema / properties / episode
        Removed value: -{
        -  "description": "TV episode: episode number.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / file
        Removed value: -{
        -  "description": "Path of the playing item.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / id
        Removed value: -{
        -  "description": "Library id of the playing item; -1 when off-library.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / label
        Removed value: -{
        -  "description": "Kodi's display label for the item.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / media
        Removed value: -{
        -  "description": "Real media type (song/episode/movie/musicvideo/…); \"unknown\" for an off-library file.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / nowplaying
        Added 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"
        +}
      • addedOutput schema / properties / progress
        Added 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"
        +}
      • removedOutput schema / properties / season
        Removed value: -{
        -  "description": "TV episode: season number.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / showtitle
        Removed value: -{
        -  "description": "TV episode: the show's name.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / subtitle
        Added 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"
        +}
      • removedOutput schema / properties / title
        Removed value: -{
        -  "description": "The item's title (may be empty).",
        -  "type": "string"
        -}
      • removedOutput schema / properties / track
        Removed value: -{
        -  "description": "Song: track number on the album.",
        -  "type": "integer"
        -}
    • Addednotify
    • Changednowplaying15 fields changed
      • removedOutput schema / properties / album
        Removed value: -{
        -  "description": "Song: the album name.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / artist
        Removed value: -{
        -  "description": "Song: the performers, an array of strings.",
        -  "type": "array"
        -}
      • addedOutput schema / properties / audio
        Added 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"
        +}
      • removedOutput schema / properties / episode
        Removed value: -{
        -  "description": "TV episode: episode number.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / file
        Removed value: -{
        -  "description": "Path of the playing item.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / id
        Removed value: -{
        -  "description": "Library id of the playing item; -1 when off-library.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / label
        Removed value: -{
        -  "description": "Kodi's display label for the item.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / media
        Removed value: -{
        -  "description": "Real media type (song/episode/movie/musicvideo/…); \"unknown\" for an off-library file.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / nowplaying
        Added 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"
        +}
      • addedOutput schema / properties / progress
        Added 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"
        +}
      • removedOutput schema / properties / season
        Removed value: -{
        -  "description": "TV episode: season number.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / showtitle
        Removed value: -{
        -  "description": "TV episode: the show's name.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / subtitle
        Added 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"
        +}
      • removedOutput schema / properties / title
        Removed value: -{
        -  "description": "The item's title (may be empty).",
        -  "type": "string"
        -}
      • removedOutput schema / properties / track
        Removed value: -{
        -  "description": "Song: track number on the album.",
        -  "type": "integer"
        -}
    • Changedpause15 fields changed
      • removedOutput schema / properties / album
        Removed value: -{
        -  "description": "Song: the album name.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / artist
        Removed value: -{
        -  "description": "Song: the performers, an array of strings.",
        -  "type": "array"
        -}
      • addedOutput schema / properties / audio
        Added 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"
        +}
      • removedOutput schema / properties / episode
        Removed value: -{
        -  "description": "TV episode: episode number.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / file
        Removed value: -{
        -  "description": "Path of the playing item.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / id
        Removed value: -{
        -  "description": "Library id of the playing item; -1 when off-library.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / label
        Removed value: -{
        -  "description": "Kodi's display label for the item.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / media
        Removed value: -{
        -  "description": "Real media type (song/episode/movie/musicvideo/…); \"unknown\" for an off-library file.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / nowplaying
        Added 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"
        +}
      • addedOutput schema / properties / progress
        Added 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"
        +}
      • removedOutput schema / properties / season
        Removed value: -{
        -  "description": "TV episode: season number.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / showtitle
        Removed value: -{
        -  "description": "TV episode: the show's name.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / subtitle
        Added 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"
        +}
      • removedOutput schema / properties / title
        Removed value: -{
        -  "description": "The item's title (may be empty).",
        -  "type": "string"
        -}
      • removedOutput schema / properties / track
        Removed value: -{
        -  "description": "Song: track number on the album.",
        -  "type": "integer"
        -}
    • Changedplay15 fields changed
      • removedOutput schema / properties / album
        Removed value: -{
        -  "description": "Song: the album name.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / artist
        Removed value: -{
        -  "description": "Song: the performers, an array of strings.",
        -  "type": "array"
        -}
      • addedOutput schema / properties / audio
        Added 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"
        +}
      • removedOutput schema / properties / episode
        Removed value: -{
        -  "description": "TV episode: episode number.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / file
        Removed value: -{
        -  "description": "Path of the playing item.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / id
        Removed value: -{
        -  "description": "Library id of the playing item; -1 when off-library.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / label
        Removed value: -{
        -  "description": "Kodi's display label for the item.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / media
        Removed value: -{
        -  "description": "Real media type (song/episode/movie/musicvideo/…); \"unknown\" for an off-library file.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / nowplaying
        Added 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"
        +}
      • addedOutput schema / properties / progress
        Added 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"
        +}
      • removedOutput schema / properties / season
        Removed value: -{
        -  "description": "TV episode: season number.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / showtitle
        Removed value: -{
        -  "description": "TV episode: the show's name.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / subtitle
        Added 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"
        +}
      • removedOutput schema / properties / title
        Removed value: -{
        -  "description": "The item's title (may be empty).",
        -  "type": "string"
        -}
      • removedOutput schema / properties / track
        Removed value: -{
        -  "description": "Song: track number on the album.",
        -  "type": "integer"
        -}
    • Changedplayfile16 fields changed
      • addedInput schema / properties / fullscreenaudio
        Added 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"
        +}
      • removedOutput schema / properties / album
        Removed value: -{
        -  "description": "Song: the album name.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / artist
        Removed value: -{
        -  "description": "Song: the performers, an array of strings.",
        -  "type": "array"
        -}
      • addedOutput schema / properties / audio
        Added 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"
        +}
      • removedOutput schema / properties / episode
        Removed value: -{
        -  "description": "TV episode: episode number.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / file
        Removed value: -{
        -  "description": "Path of the playing item.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / id
        Removed value: -{
        -  "description": "Library id of the playing item; -1 when off-library.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / label
        Removed value: -{
        -  "description": "Kodi's display label for the item.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / media
        Removed value: -{
        -  "description": "Real media type (song/episode/movie/musicvideo/…); \"unknown\" for an off-library file.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / nowplaying
        Added 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"
        +}
      • addedOutput schema / properties / progress
        Added 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"
        +}
      • removedOutput schema / properties / season
        Removed value: -{
        -  "description": "TV episode: season number.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / showtitle
        Removed value: -{
        -  "description": "TV episode: the show's name.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / subtitle
        Added 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"
        +}
      • removedOutput schema / properties / title
        Removed value: -{
        -  "description": "The item's title (may be empty).",
        -  "type": "string"
        -}
      • removedOutput schema / properties / track
        Removed value: -{
        -  "description": "Song: track number on the album.",
        -  "type": "integer"
        -}
    • Addedplayfile_with_audio_and_subtitle
    • Changedqueue15 fields changed
      • removedOutput schema / properties / album
        Removed value: -{
        -  "description": "Song: the album name.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / artist
        Removed value: -{
        -  "description": "Song: the performers, an array of strings.",
        -  "type": "array"
        -}
      • addedOutput schema / properties / audio
        Added 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"
        +}
      • removedOutput schema / properties / episode
        Removed value: -{
        -  "description": "TV episode: episode number.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / file
        Removed value: -{
        -  "description": "Path of the playing item.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / id
        Removed value: -{
        -  "description": "Library id of the playing item; -1 when off-library.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / label
        Removed value: -{
        -  "description": "Kodi's display label for the item.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / media
        Removed value: -{
        -  "description": "Real media type (song/episode/movie/musicvideo/…); \"unknown\" for an off-library file.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / nowplaying
        Added 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"
        +}
      • addedOutput schema / properties / progress
        Added 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"
        +}
      • removedOutput schema / properties / season
        Removed value: -{
        -  "description": "TV episode: season number.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / showtitle
        Removed value: -{
        -  "description": "TV episode: the show's name.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / subtitle
        Added 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"
        +}
      • removedOutput schema / properties / title
        Removed value: -{
        -  "description": "The item's title (may be empty).",
        -  "type": "string"
        -}
      • removedOutput schema / properties / track
        Removed value: -{
        -  "description": "Song: track number on the album.",
        -  "type": "integer"
        -}
    • Changedsearchmedia5 fields changed
      • changedInput schema / properties / artist / description
        Previous 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."
      • addedInput schema / properties / episodetitle
        Added 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"
        +}
      • changedInput schema / properties / number / description
        Previous 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."
      • addedInput schema / properties / song
        Added 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"
        +}
      • changedInput schema / properties / title / description
        Previous 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."
    • Addedset_audio_and_subtitle
    • Addedskipnext
    • Addedskipprevious
    • Changedstop15 fields changed
      • removedOutput schema / properties / album
        Removed value: -{
        -  "description": "Song: the album name.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / artist
        Removed value: -{
        -  "description": "Song: the performers, an array of strings.",
        -  "type": "array"
        -}
      • addedOutput schema / properties / audio
        Added 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"
        +}
      • removedOutput schema / properties / episode
        Removed value: -{
        -  "description": "TV episode: episode number.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / file
        Removed value: -{
        -  "description": "Path of the playing item.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / id
        Removed value: -{
        -  "description": "Library id of the playing item; -1 when off-library.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / label
        Removed value: -{
        -  "description": "Kodi's display label for the item.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / media
        Removed value: -{
        -  "description": "Real media type (song/episode/movie/musicvideo/…); \"unknown\" for an off-library file.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / nowplaying
        Added 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"
        +}
      • addedOutput schema / properties / progress
        Added 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"
        +}
      • removedOutput schema / properties / season
        Removed value: -{
        -  "description": "TV episode: season number.",
        -  "type": "integer"
        -}
      • removedOutput schema / properties / showtitle
        Removed value: -{
        -  "description": "TV episode: the show's name.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / subtitle
        Added 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"
        +}
      • removedOutput schema / properties / title
        Removed value: -{
        -  "description": "The item's title (may be empty).",
        -  "type": "string"
        -}
      • removedOutput schema / properties / track
        Removed value: -{
        -  "description": "Song: track number on the album.",
        -  "type": "integer"
        -}
  2. 16 tool updatesv0.1.0
    • First observedcontributors
    • First observeddropplaylists
    • First observedgetplaylist
    • First observedhistory
    • First observedinstances
    • First observedmute
    • First observednowplaying
    • First observedpause
    • First observedplay
    • First observedplayfile
    • First observedqueue
    • First observedrpc
    • First observedsearchmedia
    • First observedstop
    • First observedunmute
    • First observedvolume

TDQS

A3.8/5.0

Scored across 22 tools

Disambiguation4/5

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.

Naming Consistency3/5

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.

Tool Count4/5

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.

Completeness4/5

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

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers