This repository provides an MCP (Model Context Protocol) server for Kodi.
It exposes a curated set of Kodi operations (Kodi JSON-RPC + the Kodi MCP bridge addon) as MCP tools, so agent clients (like VS Code/Cline) can control and inspect Kodi in a structured way.
For the canonical repo publish/install/update behavior, see: project-config/REPO_WORKFLOW_RUNBOOK.md
For the current local handoff state and next TODOs, see: project-config/CURRENT_STATE.md
Server install
- Clone this repository on the host that will run the MCP server.
- Create a virtual environment and install the package:
python3 -m venv .venv
.venv/bin/pip install -e .- Copy
.env.exampleto.envand set at least:
KODI_JSONRPC_URL=http://<kodi-host>:8080/jsonrpc
KODI_BRIDGE_BASE_URL=http://<kodi-host>:8765
KODI_BRIDGE_TOKEN=<same-token-configured-in-service.kodi_mcp>
REPO_BASE_URL=http://<server-host>:8010REPO_BASE_URL must be reachable from Kodi and any remote MCP client that needs repository files or screenshot URLs.
For local-only use, keep the default MCP_BIND_HOST=127.0.0.1; authentication is
optional. For a LAN bind, also set a non-loopback MCP_BIND_HOST and
MCP_API_KEY. See Security and deployment policy.
- Start the supported server entry point (default port
8010):
.venv/bin/kodi-mcp-serverFirst-time bridge bootstrap (ordinary remote user)
Kodi 19–22 do not expose a stock JSON-RPC method that installs an arbitrary ZIP,
adds a repository/source, or executes Kodi's InstallAddon/InstallFromZip
built-ins. A bridge-absent target therefore requires a one-time user-mediated
Kodi flow; Kodi MCP does not bypass that security boundary or silently enable
Unknown Sources.
- The server operator provides the official
service.kodi_mcprelease ZIP and matchingbridge-bootstrap.json. In a source checkout, the release maintainer can prepare the exact authoritative bundle without contacting Kodi:
.venv/bin/python scripts/prepare_bridge_bootstrap.py --source /path/to/kodi_mcp_addon- Set
REPO_BASE_URLto the HTTPS URL Kodi/users can reach. The default manifest path isaddon/bridge-bootstrap.json; override it withKODI_MCP_BRIDGE_BOOTSTRAP_MANIFESTwhen needed. - Start the server and call
bridge_bootstrap_status. - If it returns
state=user_action_required, compare the returned SHA-256, make that exact ZIP visible to Kodi (download on the Kodi device or use a user-approved network source), then use Add-ons → Install from zip file. Review Kodi's Unknown Sources warning yourself; MCP will not change the setting. - Configure service.kodi_mcp → Kodi MCP → MCP shared token to match
KODI_BRIDGE_TOKEN, then callbridge_bootstrap_statusagain. - Do not treat installation as complete until the result is
state=already_installed,verified=true, andnext_stage=managed_deployment. This checks Kodi metadata plus the running bridge's exact version, source Git SHA, and source fingerprint. A wrong build is routed to the existing authoritative update/normalization flow instead of being accepted.
The bootstrap status operation is read-only and idempotent. Cancellation, interrupted installation, a disabled/unconfigured service, an unavailable bundle, or an identity mismatch remains an explicit non-success state on the next call. Future bridge upgrades use the existing authoritative update flow; the one-time ZIP step is not repeated.
First-time repository/managed-addon onboarding (after bridge verification)
- Start this server and confirm
bridge_bootstrap_statusis verified. - Call
repository_bootstrap_install. It accepts no arguments, generates and validates only the manifest-declaredrepository.kodi-mcp, uploads it through the configured bridge connection, and asks the bridge to install only that fixed staged ZIP. - For a brand-new target addon, use Kodi UI: Add-ons → Install from repository → Kodi MCP Repository → target addon → Install.
This bounded repository bootstrap does not expose a generic ZIP, URL, addon-id, filesystem-path, or Kodi-builtin installer. It works when the server and Kodi are on different hosts because the artifact is transferred over the configured bridge HTTP connection; no shared filesystem is required.
repository_readiness is the zero-argument read-only companion. It compares
the installed fixed repository identity with the canonical manifest and asks the
configured bridge to parse the installed repository URLs and probe metadata,
checksum, and one metadata-derived package from Kodi's network context. The
bridge reports repository timestamps and linked entries from Kodi's addon
database as best-effort internal evidence, while explicitly declining to infer
refresh completion or catalog freshness.
repository.kodi-mcp is generated per server so its repository URLs come from
that server's configured REPO_BASE_URL. Its invariant identity is declared in
src/kodi_mcp_server/repository_addon_manifest.json; the current canonical
version is 1.0.4. Versions increase monotonically under semantic versioning, and
1.0.0 through 1.0.3 remain historical identities that must not be reused for a
different canonical payload. Generation, automatic staging, bootstrap validation,
and the latest.zip alias all derive from the manifest. Artifact modification
time is never version authority. A future canonical payload requires a manifest
version bump before generation or use.
Because only invariant identity lives in the manifest, the same implementation supports a server and Kodi on localhost, separate LAN hosts, or behind a reverse proxy. No environment URL is stored in the manifest.
Managed addon loop (after repo is installed in Kodi)
- Register local addon:
managed_addon_register - Build/publish/stage/apply:
managed_addon_build_publish_stage_and_apply - If needed:
managed_addon_validate_state
Success = verification.apply_verified == true
Retry only if verification.can_retry == true
- Rich bridge-backed control requires
service.kodi_mcpto be installed, enabled, and configured with the shared token: https://github.com/kcook98765/kodi_mcp_addon - Before the bridge exists, Kodi MCP can still use stock JSON-RPC for status and
bridge_bootstrap_status; bridge-dependent tools remain unavailable. - The server exposes only the validated configured bridge bundle at
/bootstrap/manifest.jsonand/bootstrap/service.kodi_mcp.zip. - After the one-time user-mediated ZIP install, the bridge supplies GUI, health, staging, and authoritative update capabilities.
- Kodi-resident bridge addon source is owned by the standalone
kodi_mcp_addonrepo, not this server repo.
Run by your MCP client (Cline) as a local process:
- Command:
kodi-mcp - Transport: stdin/stdout
Cline config (stdio)
{
"mcpServers": {
"kodi-mcp": {
"command": "kodi-mcp",
"args": [],
"env": {
"KODI_JSONRPC_URL": "http://kodi.local:8080/jsonrpc",
"KODI_BRIDGE_BASE_URL": "http://kodi.local:8765"
}
}
}
}The HTTP endpoint is /mcp. Use the supported entry point so bind policy is
validated before Uvicorn opens a listener:
kodi-mcp-serverIt defaults to 127.0.0.1:8010. For an authenticated LAN bind, set
MCP_BIND_HOST and MCP_API_KEY in the protected repo-root .env (or a
service-owned environment file), then run the same command. Do not put a real
key directly in a command-line argument or URL.
{
"mcpServers": {
"kodi-mcp-remote": {
"type": "streamableHttp",
"url": "http://<server-host>:8010/mcp",
"disabled": false,
"headers": {
"x-mcp-api-key": "<key-from-your-local-secret-configuration>"
}
}
}
}The key is accepted only in the x-mcp-api-key header. Query-string keys,
Bearer headers, duplicate headers, malformed values, and oversized values are
rejected with the same non-reflective 401 Unauthorized response.
Kodi MCP exposes mutation-capable operations. The secure default therefore separates local development from remotely reachable binds:
| Deployment | Bind | Auth |
|---|---|---|
| Local development | loopback (127.0.0.1, ::1, or localhost) |
optional |
| Trusted LAN | explicit non-loopback address or wildcard | API key required by default |
| Internet/untrusted network | loopback behind a trusted HTTPS reverse proxy or secure tunnel | API key required; TLS required at the proxy/tunnel boundary |
MCP_BIND_HOST defaults to 127.0.0.1; MCP_PORT defaults to 8010. Every
non-loopback bind—including 0.0.0.0, ::, RFC1918 IPv4, IPv6 ULA/link-local,
public addresses, and non-localhost hostnames—is treated as remote-capable.
This is a conservative bind classification, not a claim about firewall or
router reachability.
A remote-capable bind without MCP_API_KEY refuses to start. Intentional
unauthenticated home-LAN use remains available only by explicitly setting:
MCP_ALLOW_INSECURE_REMOTE=true
This override emits a startup warning. Use it only on a network whose clients
and routing you explicitly trust; never use it for an internet-facing,
port-forwarded, proxied, tunneled, or otherwise untrusted deployment. Values
other than exact case-insensitive true, false, or 0 are configuration
errors; malformed values never enable the override.
The application provides API-key authentication, not TLS. A key sent over
plain HTTP can be stolen by a hostile network observer. For untrusted networks,
bind Kodi MCP to loopback, terminate HTTPS at a trusted reverse proxy or secure
tunnel on the same trusted host/network boundary, preserve the
x-mcp-api-key request header, and do not expose the loopback listener directly.
Do not configure the proxy to bypass application authentication. Kodi MCP does
not use X-Forwarded-* headers to weaken or change its bind/auth decision.
The API-key gate covers all StreamableHTTP routes under /mcp, legacy
/tools/* routes, /status, and detailed repo-health diagnostics. Minimal
/health remains unauthenticated and returns only service liveness. Repository
and validated bridge-bootstrap downloads remain unauthenticated so Kodi can
consume them; treat published artifacts as public to anyone who can reach the
server. No permissive CORS policy is enabled, and authenticated mutation
endpoints do not emit Access-Control-Allow-Origin: *.
To avoid typing a secret into shell history during an interactive session:
read -rsp 'MCP API key: ' MCP_API_KEY && printf '\n'
export MCP_API_KEY
kodi-mcp-serverFor persistent services, prefer a permission-restricted environment file rather than putting the key in the unit's command line or a public configuration file.
Behavior change: existing supported-entry-point configurations that bind
0.0.0.0, ::, a LAN address, or another non-loopback host without an API key
now refuse to start. Configure MCP_API_KEY, return to loopback, or deliberately
opt into trusted-LAN insecure mode with MCP_ALLOW_INSECURE_REMOTE=true.
Direct uvicorn ... --host ... invocation is no longer the documented/supported
launch path. For migration safety the application recognizes Uvicorn's bind
argument and applies the same startup policy; if it disagrees with
MCP_BIND_HOST, startup fails. Prefer kodi-mcp-server so bind policy and the
actual listener use one configuration.
The same FastAPI app also exposes HTTP endpoints under /health, /status, and /tools/*.
These are useful for debugging and for the included CLI wrapper, but MCP (stdio or remote) is the primary interface.
Required environment variables:
KODI_JSONRPC_URL(e.g.http://kodi.local:8080/jsonrpc)KODI_BRIDGE_BASE_URL(e.g.http://kodi.local:8765)
Optional:
KODI_JSONRPC_USERNAME,KODI_JSONRPC_PASSWORDKODI_TIMEOUTMCP_BIND_HOST(default127.0.0.1) andMCP_PORT(default8010)MCP_API_KEY(optional on loopback; required by default for non-loopback HTTP)MCP_ALLOW_INSECURE_REMOTE(default false; explicit trusted-LAN-only escape hatch)REPO_BASE_URLfor repo, first-install bridge bundle, and screenshot URLs visible to Kodi/clients on other hostsKODI_MCP_BRIDGE_BOOTSTRAP_MANIFESTfor the pinned bridge bundle manifest (defaultaddon/bridge-bootstrap.json)KODI_SCREENSHOT_STORE_DIR,KODI_SCREENSHOT_RETENTION_SECONDS,KODI_SCREENSHOT_MAX_FILESKODI_VISION_MODEL_URL,KODI_VISION_MODEL_NAME; when unset, screenshot capture remains available but vision-analysis tools are not exposed
For a one-host setup, these URLs may all use localhost. For a split-host setup, use hostnames or IPs that are reachable from the machine that consumes each URL:
- Kodi/users must reach
REPO_BASE_URLfor repository files and the one-time bridge bundle. - The server must reach
KODI_JSONRPC_URL; bridge-backed tools additionally requireKODI_BRIDGE_BASE_URL. - Remote MCP clients must reach the configured MCP URL and screenshot URLs returned under
/screenshots/; use HTTPS outside a trusted network.
Local development can use a repo-root .env file copied from .env.example.
Process environment values take precedence over .env values. Keep .env,
.env.*, local backups, keys, and logs out of Git.
Once connected, try these MCP tools first:
kodi_statusbridge_bootstrap_status(works through stock JSON-RPC when the bridge is absent)bridge_healthbridge_runtime_info
GUI helpers:
kodi_gui_actionsends basic navigation actions (up,down,left,right,select,back,home,context,info) and the cleanup actionstop.kodi_gui_screenshotcaptures a Kodi GUI screenshot through the bridge addon, stores it on the MCP server by default, and returns a/screenshots/<id>.pngURL.kodi_gui_statereturns compact Kodi window/control/player state for UI verification.addon_executelaunches an addon through Kodi JSON-RPC without using the legacy HTTP companion endpoint. It returns post-launchgui_stateby default. Useexpect_window/expect_fullscreenfor UI or navigation addons; reserveexpect_playerfor tasks that explicitly require media playback.- Use
addon_listto discover installed IDs beforeaddon_detailsoraddon_execute. Unknown IDs reported byaddon_detailsare returned asnot_found;addon_executekeeps Kodi's broader parameter rejection generic because addon-specificparamscan also be invalid. - These can assist first-install UI navigation, but deterministic bridge/repo state checks should remain the primary workflow.
Addon source and log triage helpers:
addon_source_inspectreads addon identity, extensions, Python entrypoints, tests, andPROJECT_MAP.mdstatus from an allowlisted server-local source tree or known agent mount such as/srv/workspaces/....addon_project_map_statusreports whether an addon source tree hasPROJECT_MAP.md.addon_source_treereturns a compact addon file tree for agent planning.bridge_log_recent_errorsfilters recent bridge/Kodi log lines down to error-like entries, with an optional pattern.
Video-library discovery helpers:
kodi_library_summaryreturns movie, TV-show, season, and episode totals from Kodi's nativelimits.totalmetadata. Each count call requests at most one sentinel item; it never downloads the full library.kodi_library_searchsearches one explicit media type (movie,tvshow, orepisode) using Kodi's native titlecontainsfilter. This is deterministic substring search, not fuzzy, semantic, cast, plot, filename, or path search. Matching is case-insensitive on the supported Kodi 19–22 targets.kodi_library_browseexposes boundedrecent_movies,recent_episodes,movie_genres,tvshow_genres,movie_sets,movie_tags, andtvshow_tagsviews.kodi_tv_seasonsaccepts atvshow_idreturned by search and lists that show's seasons.kodi_tv_episodesaccepts the same ID plus a season number and lists episodes.- Every listing/search uses Kodi-side
start/endlimits.limitdefaults to 10 and is rejected above the hard maximum of 50. Results reportstart,end,total, requestedlimit, andhas_more. - Results include stable Kodi IDs and concise identifying/play-state metadata. Raw media files and local paths are intentionally omitted. Artwork is limited to three useful references and drops filesystem/network-share references, credential-bearing URLs, and common token-bearing URLs.
A movie workflow from unknown contents to existing playback:
{"tool":"kodi_library_search","arguments":{"query":"Alien","media_type":"movie","limit":5}}
{"tool":"kodi_player_open","arguments":{"media_type":"movie","item_id":123}}Use the id returned by the first call as item_id; do not copy the illustrative ID above.
A TV hierarchy workflow:
{"tool":"kodi_library_search","arguments":{"query":"Example Show","media_type":"tvshow","limit":5}}
{"tool":"kodi_tv_seasons","arguments":{"tvshow_id":456,"limit":20}}
{"tool":"kodi_tv_episodes","arguments":{"tvshow_id":456,"season":1,"limit":20}}Again, use the discovered tvshow ID. Empty pages are successful with empty:true; an invalid/nonexistent TV-show ID is a model-visible not_found error.
Music-library discovery helpers:
kodi_music_summaryreturns artist, album, and song totals from nativelimits.total; each of its three fixed count calls requests at most one sentinel item.kodi_music_searchsearches exactly one type: artist name (artist), album title (album), or song title (title). It uses Kodi's native case-insensitivecontainsoperator on the supported Kodi 19–22 targets. It is substring search, not fuzzy, semantic, cross-type ranking, lyrics, filename, or path search.kodi_music_browseexposes boundedrecent_albums,recent_songs, andgenrespages.kodi_artist_albumsvalidates a discovered artist ID, then lists albums for that artist without implicitly broadening to contributor-only roles.kodi_album_songsvalidates an album ID, then lists its songs in Kodi's native track order. Multi-artist names and IDs and compilation status remain explicit.- All music pages default to 10 results, reject limits above 50, use Kodi-side pagination, and return native totals. Results omit raw media paths and bound nested artist/genre lists to 20 values. Artwork is reference-only, limited to three entries, and uses the same filesystem/share/credential/token screening as video discovery.
A music workflow from unknown contents to normal audio playback:
{"tool":"kodi_music_search","arguments":{"query":"Example Artist","media_type":"artist","limit":5}}
{"tool":"kodi_artist_albums","arguments":{"artist_id":123,"limit":10}}
{"tool":"kodi_album_songs","arguments":{"album_id":456,"limit":20}}
{"tool":"kodi_player_open","arguments":{"media_type":"song","item_id":789}}
{"tool":"kodi_player_active","arguments":{}}
{"tool":"kodi_player_item","arguments":{"playerid":0}}Use IDs returned by the preceding call, not the illustrative IDs above. Kodi normally reports the active audio player as ID 0; discover it with kodi_player_active rather than assuming. Pass that returned ID to item, pause, seek, and stop, and stop playback after controlled tests. kodi_player_open also accepts media_type:"album"; Kodi's native album item starts immediate album playback without this server clearing, replacing, or enqueueing a playlist.
Settings administration helpers:
kodi_settings_listlists only the small product safety policy, not Kodi's unrestricted setting universe. It supports exact section/category and writable filters, bounded text search,start, andlimit; the default is 10 and the hard maximum is 25.kodi_setting_getreads one listed setting and returns its current value, audited type, constraints, supported Kodi major versions, and whether MCP policy permits writes.kodi_setting_setaccepts one setting and one JSON value. It rejects unknown, read-only, unsafe, and sensitive IDs before mutation; rejects silent string-to-boolean/integer coercion; enforces numeric range and exact step, finite numbers, allowlisted enum/select values, and bounded control-free strings; performs at most oneSettings.SetSettingValue; then reads the setting again and succeeds only when the observed value matches the request.- Setting writes are deliberately conservative: no batch operation, arbitrary setting key, addon setting, path/source administration, credential or token access, network-service enabling, repository/security change, reset, or generic JSON-RPC mutation is exposed. Sensitive-looking IDs are excluded and values containing credentials, URLs with userinfo, filesystem/share paths, or control characters fail closed without being returned.
filelists.showextensions,lookandfeel.skinzoom,locale.country, andsubtitles.styleare writable on Kodi 19–22.subtitles.marginverticalis writable only on Kodi 20–22 because Kodi 19 does not expose that number setting.filelists.showhiddenandvideoplayer.adjustrefreshrateare readable but intentionally not writable.- Read-only
Settings.GetSettingsmetadata calls may use the transport's bounded read retry.Settings.SetSettingValueis never automatically retried, and the MCP mutation advertises neither read-only nor idempotent behavior.
Discover and change a setting safely:
{"tool":"kodi_settings_list","arguments":{"writable":true,"limit":10}}
{"tool":"kodi_setting_get","arguments":{"setting_id":"filelists.showextensions"}}
{"tool":"kodi_setting_set","arguments":{"setting_id":"filelists.showextensions","value":false}}Use the returned before value to restore the setting with a second explicit call when performing a temporary administration or acceptance workflow.
Playback helpers:
kodi_player_activereturns active Kodi players.kodi_player_itemreturns the current item for a player.kodi_player_seekseeks a player to an absolute timestamp in seconds.kodi_player_pausepauses without toggling playback back on.kodi_player_stopstops a player and, by default, verifies playback stays inactive across a short settle window.
Player item, pause, and stop calls report a stale or inactive playerid with guidance to call kodi_player_active. Seek rejections remain generic because Kodi's -32602 can also mean the current item is not seekable; the error tells callers to verify both conditions rather than guessing.
Autonomous agents should use these MCP tools instead of direct Kodi JSON-RPC, bridge HTTP, host-control scripts, or curl fallbacks. If a required operation is missing from MCP, add a curated MCP tool rather than teaching agents a new escape hatch.
tools/list advertises Draft 2020-12 outputSchema contracts for every stable
result tool. Calls to those tools return the existing JSON envelope in TextContent
for backwards compatibility and a corresponding validated envelope in
structuredContent. The envelope covers both success and application-level
failure (ok, tool, data, error, error_type, error_code, latency,
request identity, and raw diagnostics). Tool failures remain model-visible with
isError: true and a meaningful error.
Stable result families add required fields for status, GUI state, screenshots,
bounded logs, source inspection, active players, and managed-addon validation.
Pass-through and evolving mutation results use intentionally broader data
schemas inside the stable envelope rather than guessed narrow fields. Two highly
heterogeneous tools intentionally remain schema-less and text-only:
addon_execute (optional player/GUI verification changes its shape) and
jsonrpc_introspect (the Kodi API description varies by version and options).
Compatibility details:
- Screenshot metadata is structured, while image bytes remain a canonical MCP
ImageContentblock when requested and within the inline limit. Base64 is not copied intostructuredContent. - Log text remains in the bounded compatibility
TextContent. Structured log output contains truncation/count/byte metadata only, so a large log is not duplicated. - Every tool has standardized MCP behavior hints. Read-only hints are used only for operations that do not modify state; mutating tools are split between additive/non-destructive and potentially destructive operations. Idempotency is not claimed for mutations, and only arbitrary addon execution is marked as open-world.
- The server validates structured results against the exact schema advertised by
tools/list. A mismatch fails closed as anoutput_contract_errorinstead of emitting a misleading successful structured result.
If you’re testing the remote transport directly, you can also do a minimal curl initialize:
curl -i -N http://<server-host>:8010/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "x-mcp-api-key: ${MCP_API_KEY}" \
--data-binary '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'The repo system has a known rule: brand-new addons require a one-time manual install in Kodi UI, and updates can be automated after that.
See the runbook:
- project-config/REPO_WORKFLOW_RUNBOOK.md
KODI_BRIDGE_BASE_URLset (bridge addon HTTP base URL)KODI_BRIDGE_TOKENset- Must match Kodi addon setting: service.kodi_mcp → mcp_token
- Kodi is running with service.kodi_mcp enabled
Note: first-time repo installation no longer requires a separate staging action — the server auto-stages the current dev repo zip once registration is healthy.
- Register the local addon source folder (must contain
addon.xml):
{ "source_path": "C:/dev/addons/plugin.video.foo" }- Build → publish into dev repo → build dev repo zip → stage to Kodi:
{
"managed_addon_id": "plugin.video.foo",
"version_policy": "bump_patch",
"repo_version": "2026.04.08.1",
"verify": true
}- Validate state (fast read-only readiness report):
{ "managed_addon_id": "plugin.video.foo" }Example tool call:
{
"managed_addon_id": "plugin.video.foo",
"version_policy": "bump_patch",
"repo_version": "2026.04.08.1",
"verify": true
}Success signal (only reliable): verification.apply_verified == true
For split-host agents that already built a zip, prefer the pathless artifact workflow:
artifact_upload_ziprepo_publish_stage_apply_artifactor its agent-oriented aliasaddon_dev_loopkodi_gui_state,kodi_gui_screenshot,kodi_player_*, or addon-specific checks for visual/behavioral evidence
artifact_upload_zip validates the zip structure and addon.xml; repo_publish_stage_apply_artifact / addon_dev_loop publishes, stages, applies, and returns apply_verified, installed_version_after, apply_status, can_retry, and failure_reason in one response.
Retry behavior:
- Retry only when
verification.can_retry == true - Sleep
verification.retry_delay_seconds(if present) - Stop when
verification.can_retry == false - Use
verification.retry_hintas the operator-readable reason
Key verification.apply_status values:
applied— version changed to targetalready_current— target already installedrepo_not_installed— one-time repo install requiredrepo_not_ready— repo refresh/metadata not readyaddon_not_found— addon not visible in repo metadata*_attempted_not_verified— install/update requested but not confirmedbridge_unreachable— Kodi bridge not reachablefailed— unknown failure (inspect output)
Operator rule: If the loop cannot complete, run managed_addon_validate_state and follow its output.
- Follow
bridge_bootstrap_statusfor the one-time exact bridge ZIP install; do not bypass Kodi's Unknown Sources warning. - Configure the token: Kodi → Add-ons → Services → Kodi MCP Service → Configure → Kodi MCP → MCP shared token
- Re-run
bridge_bootstrap_statusand require exact identity verification. - Install + enable Kodi MCP Repository (
repository.kodi-mcp) once if it is missing - For each brand-new target addon: Kodi → Add-ons → Install from repository → Kodi MCP Repository → target addon → Install
- Rerun the managed addon apply/update workflow after the first install
Note: a staged dev-repo.zip is repository content used by the server/bridge refresh loop; it is not itself an installable Kodi add-on zip.
Troubleshooting rule: If anything fails, run managed_addon_validate_state first.
When you run the FastAPI server (the same one used for remote MCP), these endpoints are also available:
GET /healthGET /status/tools/*(legacy HTTP endpoints used bykodi-cli)
The /tools/* endpoints are not the primary integration surface; they exist for debugging and backwards compatibility.
They are not MCP and are not used by MCP clients.
When MCP_API_KEY is configured, /tools/*, /status, /repo-health, and
/repo/health require the same key. /health remains a minimal public liveness
endpoint.
Example unit file (Linux). Put deployment values, including MCP_API_KEY, in a
root-owned 0600 file at /etc/kodi-mcp-server.env rather than in the command
line or unit text:
[Unit]
Description=Kodi MCP Server (FastAPI + Remote MCP)
After=network.target
[Service]
Type=simple
User=kodi
WorkingDirectory=/opt/kodi_mcp_server
EnvironmentFile=/etc/kodi-mcp-server.env
ExecStart=/opt/kodi_mcp_server/.venv/bin/kodi-mcp-server
Restart=on-failure
RestartSec=2
[Install]
WantedBy=multi-user.targetFor a non-loopback service, the environment file must set MCP_BIND_HOST and
MCP_API_KEY; it may set MCP_PORT (default 8010). Put TLS in a trusted
reverse proxy or secure tunnel when clients cross an untrusted network.
Symptom: kodi_status reports JSON-RPC ok but bridge error, or managed apply reports bridge_unreachable.
Action:
- Run
bridge_bootstrap_statusfirst. - If
installed=false, follow its one-time user action and exact artifact identity. - If
installed=true, ensure the service is enabled and its token matches. - Never enable Unknown Sources or install an unverified same-ID ZIP automatically.
Symptom: apply_status = repo_not_installed; dev_setup_available may be true.
Action:
- Install
repository.kodi-mcponce. - Then use Add-ons → Install from repository → Kodi MCP Repository → target addon → Install.
- Do not try to install the staged
dev-repo.zip; it is repository content, not an installable add-on zip.
Symptom: apply_status = repo_not_ready.
Action:
- Wait a few seconds and retry
- Or manually run “Check for updates” in Kodi
Symptom: apply_status = addon_not_found.
Action:
- Retry once
- If still failing: confirm repo installed and repo zip staged correctly (
managed_addon_validate_state)
Symptom: apply_status = install_attempted_not_verified or update_attempted_not_verified.
Action:
- Retry (short delay)
- If persistent: verify repo enabled and check Kodi update settings (optionally trigger update manually)
Symptom: apply_status = failed.
Action:
- Run
managed_addon_validate_state - Inspect: artifacts, repo_ready_check, bridge state
The deterministic suite and release gate target Python 3.13:
.venv/bin/python -m pip install -e ".[ci]"
.venv/bin/python -m pytest
.venv/bin/python -m compileall -q src scripts
.venv/bin/python -m kodi_mcp_server.release_gate --project-root .See CI and reproducible release gates for the tier model, isolated wheel/sdist validation, manual release-readiness workflow, known-warning policy, private compatibility-lab boundary, and release checklist. CI does not deploy, contact Kodi, tag, or publish a GitHub Release.