Skip to main content
Glama
kdeconnect-mcp

kdeconnect-mcp

by DaBlitzStein

kdeconnect-mcp

GitHub stars PyPI

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:

  1. Redaccion en la ingesta: el listener redacta antes de INSERT. El texto original solo existe en memoria durante el evento.

  2. Hash con HMAC (content_hash) para deduplicar/auditar sin guardar texto.

  3. Defensa en profundidad: las respuestas MCP vuelven a pasar por el redactor, tambien las lecturas en vivo de DBus.

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

Related MCP server: iMessage MCP

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.

uvx kdeconnect-mcp serve    # desde PyPI
# sin pasar por PyPI: uvx --from git+https://github.com/DaBlitzStein/kdeconnect-mcp kdeconnect-mcp serve

Configuracion en un agente MCP (opencode, Claude Code, Cursor, LibreFang...):

"kdeconnect": {
  "type": "local",
  "command": ["uvx", "kdeconnect-mcp", "serve"],
  "enabled": true
}

Listener permanente (captura aunque no haya agente abierto): instala la herramienta y provisiona:

uv tool install kdeconnect-mcp   # o: uv tool install git+https://github.com/DaBlitzStein/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):

  1. Descarga kcd_<version>_linux_x86_64.tar.gz y checksums.txt de GitHub a un directorio temporal.

  2. Verifica el SHA256 del tarball contra checksums.txt y aborta con error si no coincide.

  3. Extrae el binario y lo instala en ~/.local/bin/kcd (chmod +x).

  4. Escribe ~/.config/systemd/user/kcd.service (ExecStart=%h/.local/bin/kcd daemon) y kdeconnect-mcp-listen.service (ExecStart=<interprete-instalado> -m kdeconnect_mcp listen, sin depender del PATH de systemd).

  5. systemctl --user daemon-reload; salvo --no-start, hace enable --now de 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 devices lista los dispositivos vistos por el daemon.

  • kdeconnect-mcp doctor (o uv run kdeconnect-mcp doctor desde 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 cada capture.sms_poll_seconds (300 s por defecto; 0 lo 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_notifications no soportado en kcd: usa get_activity (la captura en vivo si trae las notificaciones nuevas).

  • sync_sms_history no 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 provision falla 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 — factoria kcd | 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.

Available Tools

16 tools
accept_pairingB

Acepta una solicitud de emparejamiento entrante (el movil la inicio). Requiere backend kcd.

Inputs: device_id (required). Returns: object

acknowledge_eventsC

Marca eventos como reconocidos, por ids o por antiguedad.

Inputs: ids, kind, before_minutes. Returns: object

get_activityC

Timeline unificado de actividad ya redactada.

kind: 'sms', 'call' o 'notification' (None = todo). app: filtro parcial por nombre de app (ej. 'whatsapp'). since_minutes: ventana temporal hacia atras (0 = sin limite). unread_only: solo eventos no reconocidos.

Inputs: app, kind, limit, offset, +3 more. Returns: object

get_call_logC

Historial de llamadas. only_missed=True para perdidas.

Inputs: days, limit, only_missed. Returns: object

get_conversationC

Hilo de SMS filtrado por telefono (parcial) o nombre de contacto.

Inputs: limit, address, contact. Returns: object

get_eventsA

Consumo incremental por cursor: eventos con id > after_id, en orden de llegada.

Devuelve next_after_id para la siguiente llamada (patron de stream/log). Las retiradas de notificacion actualizan la fila y no se reemiten.

Inputs: kind, limit, after_id. Returns: object

get_redaction_statsA

Conteo de redacciones por categoria (otp, card, iban, phone).

Inputs: no named parameters. Returns: object

get_statusA

Estado del servidor: listener, configuracion de captura/PII y conteos.

Inputs: no named parameters. Returns: object

list_active_notificationsC

Notificaciones activas en el movil ahora mismo (backend configurado, redactadas).

Inputs: device_id. Returns: object

list_devicesA

Dispositivos moviles vistos por el listener (desde la base de datos).

Inputs: no named parameters. Returns: object

reject_pairingC

Rechaza una solicitud de emparejamiento entrante. Requiere backend kcd.

Inputs: device_id (required). Returns: object

request_pairB

Pide emparejar un dispositivo; hay que confirmar en el movil.

Inputs: device_id (required). Returns: object

scan_devicesC

Escanea dispositivos KDE Connect. include_unpaired para emparejar nuevos.

Inputs: include_unpaired. Returns: object

search_activityC

Busca texto en titulo/cuerpo/app/contacto sobre lo ya redactado.

Inputs: query (required), kind, limit. Returns: object

sync_sms_historyC

Pide al movil las conversaciones cacheadas y las ingesta (redactadas).

Inputs: wait_seconds. Returns: object

wait_for_eventsA

Long-poll: espera (hasta timeout_seconds) a que haya eventos con id > after_id.

Recomendado para consumo en vivo: guarda next_after_id y vuelvelo a pasar.

Inputs: kind, after_id, timeout_seconds. Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.2/5.0

    Scored across 16 tools

    Disambiguation4/5

    Most tools have clearly distinct purposes (pairing, scanning, status, SMS, calls, notifications). The event family (get_activity, get_events, wait_for_events, search_activity, list_active_notifications) overlaps conceptually, but descriptions clarify different consumption modes; a few could be confused by name alone.

    Naming Consistency5/5

    All 16 tools follow a consistent verb_noun snake_case pattern (list_devices, get_status, accept_pairing, sync_sms_history). No mixed conventions or vague verbs are present.

    Tool Count4/5

    16 tools is slightly above the ideal 3-15 range, but each tool addresses a distinct need in the pairing/event/SMS/call lifecycle. The count is justified by the broad scope, though a few could be consolidated.

    Completeness4/5

    The surface covers the full pairing workflow, event consumption (timeline, cursor, long-poll, acknowledge), SMS/call history, active notifications, and redaction stats. Missing device detail/forget actions and send commands, but core monitoring workflows are complete.

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      B
      maintenance
      Enables AI agents on macOS to securely read and search the local Messages database, catch up on missed messages via a persistent inbox, and send texts or files to allowlisted chats, with optional voice note transcription and text-to-speech.
      10
      26 npm
      MIT
    • F
      license
      Not graded
      quality
      B
      maintenance
      Enables AI agents to use a real Android phone with a SIM to retrieve phone numbers, receive SMS verification codes, and manage SMS messages.
      -
    • A
      license
      A
      quality
      B
      maintenance
      Enables AI agents to see and drive a real Android phone over plain ADB: screenshots and numbered UI trees, gestures, typing with accents and emoji, SMS/RCS reading and prepared replies, notifications, files, and settings, with no root and no app installed on the phone. Safeguards mask security codes and require explicit confirmation before sending, paying, deleting or confirming anything.
      18
      2
      MIT