kdeconnect-mcp
MCP server que expone llamadas, SMS y notificaciones de un movil Android a un agente, via KDE Connect, con un sistema de PII que impide que los codigos de autorizacion (OTP), numeros de tarjeta, IBAN y telefonos completos lleguen al agente o toquen el disco. Los nombres de contacto y de app si son visibles.
movil Android ──KDE Connect v8──> kcd (Go, headless) ──socket Unix──> listener ──PII──> SQLite ──MCP──> agente
Que redacta (y que no)
| Categoria | Ejemplo | Resultado |
|---|---|---|
otp |
Tu codigo de autorizacion es 483920 |
[REDACTADO:otp] |
card |
407-1234567-8901234 |
[REDACTADO:card] |
iban |
ES91 2100 0418 4502 0005 1332 |
[REDACTADO:iban] |
phone |
+34 600 123 456 |
+34 ***456 (configurable) |
| Nombres | Ana, Mama, BBVA |
sin cambios |
Garantias:
- Redaccion en la ingesta: el listener redacta antes de
INSERT. El texto original solo existe en memoria durante el evento. - Hash con HMAC (
content_hash) para deduplicar/auditar sin guardar texto. - Defensa en profundidad: las respuestas MCP vuelven a pasar por el redactor, tambien las lecturas en vivo de DBus.
- Logs sin contenido: el listener registra kind/app/contadores, nunca el
texto. Los tests E2E escanean el fichero SQLite (incluido
-wal) buscando los secretos simulados y fallan si aparecen.
El detector de OTP combina palabras clave (codigo, autorizacion, verificacion,
otp, code, password...) con ventana de contexto y lista de apps sensibles
(authenticator, authy, bitwarden...). Anade tus bancos a sensitive_apps en la
config para que cualquier codigo suyo se redacte aunque falte la palabra clave.
Requisitos
- Linux; vale headless (sin sesion grafica, sin Qt/KDE).
- Sesion de usuario con systemd (
systemctl --user) para kcd y el listener. - uv para instalar/ejecutar (gestiona Python >= 3.11).
- Movil Android con la app KDE Connect y los plugins Notificaciones, SMS y Telefonia activos (en la app: Ajustes > Plugins).
- Opcional: backend DBus legacy si ya usas
kdeconnectd(backend: dbus).
El daemon headless kcd lo instala
kdeconnect-mcp provision (binario unico, sin Qt). Verifica el estado con:
kdeconnect-mcp doctor # o: uv run kdeconnect-mcp doctor, desde el repo
Instalacion
git clone https://github.com/DaBlitzStein/kdeconnect-mcp.git
cd kdeconnect-mcp
uv sync
uv run kdeconnect-mcp demo # prueba el pipeline con datos simulados
Sin clonar el repo (uvx, recomendado)
uvx es el equivalente a npx en Python: ejecuta el paquete sin clonar ni instalar.
# desde GitHub (disponible ya)
uvx --from git+https://github.com/DaBlitzStein/kdeconnect-mcp kdeconnect-mcp serve
# cuando este publicado en PyPI
uvx kdeconnect-mcp serve
Configuracion en un agente MCP (opencode, Claude Code, Cursor, LibreFang...):
"kdeconnect": {
"type": "local",
"command": ["uvx", "--from", "git+https://github.com/DaBlitzStein/kdeconnect-mcp", "kdeconnect-mcp", "serve"],
"enabled": true
}
Listener permanente (captura aunque no haya agente abierto): instala la herramienta y provisiona:
uv tool install git+https://github.com/DaBlitzStein/kdeconnect-mcp # o: uv tool install kdeconnect-mcp
kdeconnect-mcp provision
Registrar en opencode
En ~/.config/opencode/opencode.json:
{
"mcp": {
"kdeconnect": {
"type": "local",
"command": [
"uv", "--directory", "/ruta/a/kdeconnect-mcp",
"run", "kdeconnect-mcp", "serve"
],
"enabled": true
}
}
}
Listener permanente (recomendado)
El servidor MCP captura mientras hay una sesion de agente. Para capturar siempre (aunque el agente este cerrado), instala la herramienta y provisiona:
uv tool install git+https://github.com/DaBlitzStein/kdeconnect-mcp # o: uv tool install kdeconnect-mcp
kdeconnect-mcp provision # instala kcd + unidades systemd de usuario y las arranca
provision escribe la unidad con el interprete real de la instalacion, asi que
funciona igual desde el repo o desde uv tool. El lock (listener.lock)
garantiza un unico escritor; si el service ya corre, el servidor MCP solo lee la
misma base de datos. Al terminar, el CLI te recuerda dejar una estrella en el repo.
Operacion con kcd
kcd es un daemon de KDE Connect
(protocolo v8) escrito en Go, headless: binario unico, sin Qt ni sesion grafica.
Escucha en el socket Unix $XDG_RUNTIME_DIR/kcd/kcd.sock (o el que fije
KDCONNECT_SOCKET).
Provision
uv run kdeconnect-mcp provision --dry-run # plan completo, no descarga ni escribe
uv run kdeconnect-mcp provision # instala y arranca
provision trabaja sobre la release fijada v1.20.0 (--version vX.Y.Z para
cambiarla):
- Descarga
kcd_<version>_linux_x86_64.tar.gzychecksums.txtde GitHub a un directorio temporal. - Verifica el SHA256 del tarball contra
checksums.txty aborta con error si no coincide. - Extrae el binario y lo instala en
~/.local/bin/kcd(chmod +x). - Escribe
~/.config/systemd/user/kcd.service(ExecStart=%h/.local/bin/kcd daemon) ykdeconnect-mcp-listen.service(ExecStart=<interprete-instalado> -m kdeconnect_mcp listen, sin depender del PATH de systemd). systemctl --user daemon-reload; salvo--no-start, haceenable --nowde ambos servicios.
Emparejamiento
~/.local/bin/kcd devices # lista dispositivos y estado
~/.local/bin/kcd pair # escucha y acepta solicitudes del movil
~/.local/bin/kcd pair <deviceId> # inicia el pairing desde el escritorio
El flujo es TLS con huella SHA-256: confirma la huella en el movil cuando
aparezca la solicitud. Desde el agente, las tools scan_devices,
request_pair, accept_pairing y reject_pairing cubren lo mismo.
Plugins en el movil
En la app KDE Connect del movil, Ajustes > Plugins, activa al menos Notificaciones, SMS y Telefonia. Sin ellos kcd no reenvia eventos, aunque el emparejamiento exista.
Refresco
- El listener re-sincroniza dispositivos al conectar y mantiene abierto el stream de pairing; si el socket cae, reconecta con backoff (1s-30s).
kcd deviceslista los dispositivos vistos por el daemon.kdeconnect-mcp doctor(ouv run kdeconnect-mcp doctordesde el repo) muestra socket, version de kcd, estado de las unidades systemd y el lock del listener.- Refresco forzado:
systemctl --user restart kdeconnect-mcp-listen.service.
Limites con kcd
- SMS por polling: kcd no empuja los SMS; el listener pide las
conversaciones (
sms_request_conversations) al conectar y cadacapture.sms_poll_seconds(300 s por defecto;0lo desactiva). El movil reenvia su historial cacheado en cada ciclo: el dedup lo absorbe, pero con intervalos muy bajos hay trafico/CPU/bateria de mas (60 s funciona bien). list_active_notificationsno soportado en kcd: usaget_activity(la captura en vivo si trae las notificaciones nuevas).sync_sms_historyno soportado en kcd: devuelve un error explicito; el polling ya trae el historial.- La release v1.20.0 de kcd solo publica binario Linux x86_64; en otras
arquitecturas
provisionfalla con error claro.
Herramientas MCP
| Tool | Para que |
|---|---|
get_status |
Estado del listener, captura y PII |
list_devices |
Dispositivos conocidos (BD) |
get_activity |
Timeline filtrable (kind, app, since_minutes, ...) |
get_events / wait_for_events |
Consumo incremental por cursor (after_id); long-poll |
search_activity |
Busqueda de texto sobre lo redactado |
get_conversation |
Hilo de SMS por telefono/contacto |
get_call_log |
Llamadas; only_missed=true para perdidas |
list_active_notifications |
Notificaciones activas en el movil (solo backend DBus; en kcd, cache) |
acknowledge_events |
Marca leidos por ids o antiguedad |
get_redaction_stats |
Redacciones por categoria |
sync_sms_history |
Pide al movil las conversaciones cacheadas (solo DBus) |
scan_devices / request_pair |
Emparejamiento: listar y solicitar |
accept_pairing / reject_pairing |
Aceptar/rechazar solicitudes entrantes (kcd) |
CLI
kdeconnect-mcp serve # MCP por stdio (por defecto)
kdeconnect-mcp listen # captura en primer plano
kdeconnect-mcp sync # sincroniza SMS cacheados
kdeconnect-mcp events # timeline reciente
kdeconnect-mcp redact-test "Tu codigo es 123456"
kdeconnect-mcp demo # datos simulados, sin KDE Connect
kdeconnect-mcp doctor # diagnostico (config, kcd, systemd, KDE Connect)
kdeconnect-mcp provision # instala kcd y los services systemd de usuario
kdeconnect-mcp config-init # escribe config de ejemplo
Todas aceptan --data-dir, --config y --fake.
Configuracion
Ver config/config.example.yaml. Se carga de
~/.config/kdeconnect-mcp/config.yaml (o KDCONNECT_MCP_CONFIG).
Claves utiles:
backend:kcd(por defecto) |dbus|fake.kcd.socket_path: ruta al socket de kcd (por defecto$XDG_RUNTIME_DIR/kcd/kcd.sock).capture.sms_poll_seconds: cada cuanto se piden las conversaciones SMS (0 = off).redaction.phone.mode:off|partial(por defecto, ultimos 3) |full.redaction.keywords: palabras que activan la redaccion de codigos cercanos.redaction.sensitive_apps: apps donde todo codigo se redacta siempre.capture.ignore_apps: apps cuyas notificaciones no se capturan.
Desarrollo
uv run pytest # 93 tests: PII, store, ingesta, backends, poll SMS, tools MCP, provision
Estructura:
pii.py— motor de redaccion (categorias, solapes, enmascarado de telefono).listener.py— ingesta: redacta, deduplica, mergea llamadas, persiste.store.py— SQLite WAL + FTS5, solo texto redactado.kcd_backend.py— cliente del socket de kcd (watch NDJSON + comandos IPC).backends.py— factoriakcd|dbus|fake.dbus_backend.py— DBus KDE Connect (legacy; interfaces verificadas contra master y v24.02).fake_backend.py— movil simulado para desarrollo/tests.server.py— tools MCP;cli.py— comandos;config.py— config YAML.
Limitaciones
- Las llamadas se exponen como eventos
ringing/missedCall(no hay audio ni estado "en curso" persistente en KDE Connect). - Los SMS se reciben pidiendo las conversaciones al movil (polling; ver "Limites con kcd").
- No hay tool MCP de envio de SMS ni de respuesta a notificaciones (el backend lo soporta; extension pendiente).
- El escritorio debe estar encendido y con KDE Connect conectado al movil.
Diagramas (mermaid con Firefox headless, sin Chrome)
mermaid-cli usa Puppeteer, que por defecto baja chrome-headless-shell. Aquí se
usa el Firefox de Puppeteer en su lugar:
# una vez: descarga el Firefox de Puppeteer (~90 MB, sin Chrome)
PUPPETEER_SKIP_DOWNLOAD=1 npx -y puppeteer browsers install firefox
# renderizar cualquier .mmd (svg o png; pdf es Chromium-only)
./tools/render-mermaid.sh docs/arquitectura-kcd.mmd docs/arquitectura-kcd.png
La config tools/puppeteer.firefox.json fija {"browser": "firefox", "headless": true}
(necesario para pisar el headless: "shell" por defecto de mermaid-cli, que es Chrome).
Para ver diagramas en la terminal (flowchart y sequence) sin visor gráfico:
./tools/mmd.sh docs/flujo-ingesta.mmd
Nota: mermaid-ascii no soporta subgraph ni formas no rectangulares; los
flowcharts para terminal se escriben planos (ver docs/arquitectura-kcd-plano.mmd).
Para ERD/gantt o el diagrama con subgraphs, usar el PNG y chafa.
Release files for kdeconnect-mcp 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| kdeconnect_mcp-0.1.0.tar.gz | 311.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| kdeconnect_mcp-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 360.3 kB
Release files / kdeconnect_mcp-0.1.0.tar.gz
| Download URL | kdeconnect_mcp-0.1.0.tar.gz |
|---|---|
| Size | 311.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cc6005319e6a637b69a910fc1f844fcae32013df3beef3a409915d6961f5e6fa
|
|
BLAKE2b-256 checksum How to use checksums |
bc9c59c56dcf85a74d09b818314eac9f81e58ab4efc5ae976ba7e639b908fc89
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / kdeconnect_mcp-0.1.0-py3-none-any.whl
| Download URL | kdeconnect_mcp-0.1.0-py3-none-any.whl |
|---|---|
| Size | 48.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
14a1fc37ecf8ae995d4e98d6a8668f99008ecf431558aac2bf0ebf889e1bcfd8
|
|
BLAKE2b-256 checksum How to use checksums |
4d18fd6d2258298073e850299949453398ceb3143865a5450e9078deae470fcd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|