Skip to main content
Glama
riseblyp

mobile_claude_connect

by riseblyp

mobile_claude_connect

Un puente teléfono-PC que da a una sesión de Claude Code que se ejecuta en tu PC acceso a los datos de tu iPhone — fotos, vídeos, ubicación en vivo, contactos, calendario, portapapeles — además de un sistema de plugins que permite a Claude escribir y ejecutar sus propias automatizaciones de navegador contra servicios web con sesión iniciada.

El teléfono es solo una pantalla. Cada byte permanece en tu propia máquina y viaja por tu propia tailnet de Tailscale. No hay componente en la nube, ni servicio de terceros, y no se sube nada a ningún sitio.

Tres piezas:

Pieza

Qué es

server.py

Aplicación Flask + waitress en el puerto 8778. Sirve la PWA del lado del teléfono, acepta subidas de fotos y envíos desde la hoja de compartir, y ejecuta la cola de trabajos.

indexer.py

Incrustación CLIP + búsqueda semántica sobre la biblioteca de fotos/vídeos, almacenada en SQLite.

mcp_server.py

Un servidor MCP sobre stdio. Es con lo que Claude Code realmente habla.


Arquitectura

        iPhone                      Tailscale                    Windows PC
 ┌────────────────────┐            ┌───────────┐      ┌──────────────────────────────┐
 │ Claude app         │            │           │      │  Claude Code                 │
 │  (Remote Control)  │───────────────────────────────>│      │                       │
 │                    │            │           │      │      │ stdio                  │
 │ Bridge PWA :8778   │  upload    │  100.x    │      │  mcp_server.py  ── MCP tools  │
 │  - photo picker    │───────────>│ WireGuard │─────>│      │                       │
 │  - run Shortcut    │            │  CGNAT    │      │  server.py  :8778             │
 │  - /login mirror   │            │  range    │      │   /ingest  ──> vault/         │
 │                    │            │           │      │   /drop    ──> vault/drop/    │
 │ Shortcuts app      │  location  │           │      │   /records ──> records table  │
 │  - Claude Bridge   │  contacts  │           │      │   /job/*   ──> job queue      │
 │  - Send to Claude  │───────────>│           │      │   /login/* ──> login_session  │
 └────────────────────┘            └───────────┘      │                              │
                                                      │  indexer.py ── CLIP ── GPU    │
   iCloud for Windows                                 │  caps.py ── Playwright ──┐    │
   photo library  ─────────────────────────────────────> watch_dirs             │    │
                                                      │  bridge.db (SQLite)     │    │
                                                      └─────────────────────────┼────┘
                                                                                │
                                                                  profiles/<service>/
                                                                  (persistent cookies)

El cortafuegos solo permite 100.64.0.0/10 — el rango CGNAT de Tailscale. Nada es accesible desde la internet pública.


Related MCP server: remote-control-mcp

Superficie de herramientas MCP

Estas son las herramientas que Claude Code ve una vez registrado el servidor MCP.

Herramienta

Qué hace

photos_stats

Tamaño del índice, rango de fechas, cuántos elementos siguen sin incrustar, qué carpetas están vigiladas. Llama a esto primero para cualquier cosa relacionada con fotos.

photos_search

Búsqueda semántica CLIP sobre fotos y vídeos a partir de una frase corta en inglés, filtrable por rango de fechas, cuadro delimitador GPS y kind.

photos_by_date

Lista los recursos solo por tiempo y/o lugar, los más recientes primero, sin clasificación por contenido.

photos_places

Agrupaciones GPS aproximadas (~55 km) con recuentos de fotos y primer/último día — "dónde estaba yo, y cuándo".

photos_open

Renderiza los recursos a JPEG que Claude puede ver de verdad: HEIC se reduce de escala, un vídeo se convierte en una hoja de contactos de 6 fotogramas.

index_update

Escanea la bóveda y las carpetas vigiladas en busca de archivos nuevos y luego incrusta todo lo que aún no esté incrustado.

phone_actions

Los nombres de las acciones que el Atajo del lado del teléfono sabe realizar.

phone_request

Pone en cola un trabajo para el teléfono (ubicación actual, contactos, calendario, portapapeles, abrir un enlace profundo, notificar).

phone_job_status

Resultado de un trabajo de teléfono en cola.

capability_list

Plugins de capacidad instalados y si el perfil de navegador de cada uno tiene la sesión iniciada.

capability_howto

El contrato para escribir una nueva capacidad — devuelve capabilities/_TEMPLATE.py y las reglas.

capability_run

Ejecuta una capacidad por nombre; args se pasan directamente a su run().

capability_login

Abre un inicio de sesión humano de una sola vez: reflejado en el teléfono por defecto, o una ventana real en el PC.

records_query

Lee las cargas útiles que no son fotos que el teléfono ha enviado: ubicación, contactos, calendario, portapapeles, envíos desde la hoja de compartir.


Búsqueda semántica CLIP

Las fotos y los vídeos se incrustan con openai/clip-vit-large-patch14 (configurable). Una foto contribuye con una incrustación de imagen; un vídeo se muestrea en tres fotogramas repartidos por el 70% central del clip y las incrustaciones de los fotogramas se promedian y luego se re-normalizan. Cada vector es float32 normalizado L2 y se almacena como BLOB crudo en SQLite, de modo que una consulta es un solo numpy matmul sobre el conjunto de candidatos filtrado por fecha/geo — decenas de milisegundos sobre decenas de miles de recursos.

Una búsqueda es:

  1. Filtrar por rango de taken_at y/o un cuadro delimitador [lat_min, lat_max, lon_min, lon_max] en SQL.

  2. Incrustar la consulta de texto en inglés, hacer matmul contra la matriz de candidatos, ordenar por similitud de coseno y tomar los k primeros.

  3. Devolver candidatos, no respuestas — Claude entonces llama a photos_open y los mira antes de decir nada.

Dos notas de diseño que salieron de usar esto en la práctica:

  • Las puntuaciones son relativas. La similitud de coseno aterriza aproximadamente en 0,15–0,35 para todo. El rango importa; el número no. No hay un umbral en el que un acierto "sea" una coincidencia.

  • Las preguntas de viaje son geografía, no visión. "Encuentra fotos de mi viaje a Japón de hace tres años" no debería preguntar a CLIP cómo es Japón. photos_places agrupa las etiquetas GPS en una cuadrícula de 0,5° (~55 km) e informa de las coordenadas y el intervalo de fechas de cada grupo, de modo que Claude encuentra dónde estabas realmente y luego acota por contenido dentro de esa ventana. Un cuadro delimitador ingenuo del tamaño de un país es genuinamente peligroso aquí: un rectángulo de Japón de [24, 46, 123, 146] también se traga el sureste de Corea.

Los vídeos se almacenan en vertical: los iPhone graban en retrato como un búfer apaisado de 1920×1080 más una rotación de matriz de visualización que libav no aplica al decodificar, así que indexer._upright() lee frame.rotation y rota antes de incrustar.


Modelo de seguridad

Esto expone toda tu biblioteca de fotos y varias cuentas con sesión iniciada en un puerto HTTP. Los controles son deliberadamente simples y en capas:

  • Solo tailnet. open_firewall.ps1 crea una regla de entrada para TCP 8778 restringida a -RemoteAddress 100.64.0.0/10, el rango CGNAT de Tailscale. El tráfico nunca toca la internet pública; está cifrado de extremo a extremo con WireGuard por Tailscale.

  • Token portador compartido. Toda ruta excepto la carcasa de la PWA, /manifest.json y /health requiere el token de config.json, comparado con hmac.compare_digest para que la comprobación sea de tiempo constante.

  • El token en la cadena de consulta es un compromiso deliberado. <img src> no puede llevar una cabecera, y las acciones de Atajos del teléfono hacen que las cabeceras sean incómodas. Esto solo es aceptable porque el tráfico nunca sale de la tailnet. No expongas este puerto públicamente.

  • Contención de rutas. Cada nombre de archivo subido pasa por safe_name() (que elimina los componentes de directorio y los caracteres ilegales de Windows pero conserva Unicode, de modo que los nombres de archivo en coreano y con emojis sobreviven) y el destino resuelto se comprueba con is_relative_to(VAULT) antes de escribir nada.

  • Las contraseñas nunca se registran. /login/input filtra explícitamente lo que reenvía, y login_session pasa el texto tecleado directamente al navegador.

  • La PWA del lado del teléfono almacena el token en localStorage, de modo que lo tecleas una sola vez.


La cola de trabajos

iOS no da ninguna forma de que un PC despierte un teléfono. Así que el flujo está invertido:

  1. Claude llama a phone_request("location.current"), que inserta una fila en jobs con estado pending y devuelve un id de trabajo inmediatamente.

  2. El teléfono ejecuta el Atajo Claude Bridge — con un toque, desde el botón de la PWA, o desde una automatización programada. Hace GET a /job/next, que marca atómicamente un trabajo como taken. Si no hay nada en cola, el servidor responde 204 y el Atajo simplemente sale.

  3. El Atajo se ramifica según el nombre de action, recopila los datos y los envía con POST a /records?job=<id> o /job/<id>/done.

  4. Claude consulta phone_job_status.

Un trabajo marcado como taken que nunca se completa vuelve a pending después de job_ttl_min minutos, de modo que un Atajo interrumpido a mitad de ejecución no pierde la solicitud.

Claude debe decirte que ejecutes el Atajo en lugar de consultar en silencio — eso está escrito en el docstring de la herramienta.


Plugins de capacidad

Una capacidad es un archivo Python en capabilities/ que expone run(**kwargs) -> dict. Su docstring de módulo es la especificación — eso es lo que Claude lee para decidir si llamarla, así que documenta los argumentos, la forma de retorno y si se necesita un inicio de sesión.

Los módulos se re-importan en cada llamada (importlib.util.spec_from_file_location + exec_module), de modo que una capacidad que Claude escribió o editó hace treinta segundos está activa inmediatamente. Sin reinicio de MCP, sin reinicio del servidor.

La intención es que una integración que falta no sea un callejón sin salida. Claude tiene Write y Bash en la máquina: llama a capability_howto, escribe capabilities/<name>.py y lo ejecuta. Lo que escribe persiste y se acumula.

Dos vienen con el repositorio: webpage.py (renderiza cualquier URL en un navegador real y devuelve su texto legible, opcionalmente como usuario con sesión iniciada) y naver_mail.py (un ejemplo trabajado sustancial — intercepta los XHR JSON propios del cliente web en lugar de adivinar una API).

Escribir una

"""One line saying what this does - this line is what Claude sees in the list.

Args:
    since (str): 'YYYY-MM-DD'. Optional, defaults to 30 days ago.
    limit (int): max rows. Optional, default 20.

Returns:
    {"orders": [{"date","title","price","url"}], "count": int}

Notes:
    Requires a one-time manual login (PROFILE below).
"""

PROFILE = "example"                       # omit for capabilities needing no login
LOGIN_URL = "https://example.com/login"


def run(since: str = "", limit: int = 20) -> dict:
    from caps import browser

    with browser(PROFILE) as page:
        page.goto("https://example.com/orders", wait_until="domcontentloaded")
        if "login" in page.url:
            return {"error": "logged out",
                    "fix": f"call capability_login('{PROFILE}', '{LOGIN_URL}')"}
        rows = page.query_selector_all("li.order")
        if not rows:
            return {"error": "no rows matched 'li.order' - selector likely stale",
                    "url": page.url}
        ...

Consulta capabilities/_TEMPLATE.py para la versión anotada completa. Las reglas, que capability_howto devuelve textualmente:

  • Pasa siempre por caps.browser(PROFILE). Nunca lances Playwright directamente.

  • Falla ruidosamente. Una lista vacía tras un rediseño del sitio se lee como "no tienes nada", y el usuario actuará en consecuencia. Devuelve {"error": ...} nombrando el selector que falló.

  • Nunca automatices pagos, confirmaciones de pedido o transferencias de dinero. Recopila, decide, prepara la pantalla — el humano toca el último botón.

  • Nunca automatices un inicio de sesión (abajo).

Los inicios de sesión son deliberadamente manuales

Automatizar un inicio de sesión pierde contra la 2FA y los captchas, y un montón de intentos fallidos bloquea tu cuenta. Así que no está soportado. En su lugar:

  1. Claude llama a capability_login(profile, login_url).

  2. Por defecto, un Chromium headless se inicia en el PC y su pantalla se refleja en tu teléfono en /login — fotogramas JPEG a ~3 fps, con toques y pulsaciones de teclado enviados de vuelta. Nada aparece en la pantalla del PC, así que no puede robar el foco de un juego. Pasa on_pc=True para cuentas que prefieras no teclear a través del puente.

  3. Tecleas la contraseña tú mismo, una vez.

  4. Las cookies persisten y cada ejecución posterior las reutiliza.

La persistencia es más sutil que "usar un perfil persistente". Chromium descarta las cookies de sesión — las que no tienen caducidad — cuando el contexto se cierra, y para muchos servicios (los NID_AUT / NID_SES de Naver, por ejemplo) esas son el inicio de sesión. Un directorio de perfil puede parecer completamente poblado y seguir sin sesión iniciada. Así que caps.browser() llama a load_state() al abrir y a save_state() al cerrar, haciendo un viaje de ida y vuelta de las cookies a través de profiles/<service>/storage_state.json, y login_session hace instantáneas de ellas cada ~10 segundos por si el teléfono se aleja a mitad del inicio de sesión.

caps.launch_kwargs() prefiere channel="chrome" (tu Chrome real instalado) sobre el Chromium incluido de Playwright, porque Google en particular marca la compilación incluida durante el inicio de sesión.


Requisitos

  • Windows (el código usa ctypes.windll para la prioridad de procesos y CREATE_NO_WINDOW)

  • Python 3.10+ (usa sintaxis de tipos X | Y y Path.is_relative_to)

  • Tailscale tanto en el PC como en el teléfono, en la misma tailnet

  • Una GPU NVIDIA es opcional pero muy recomendada. CLIP se ejecuta en CPU (establece "device": "cpu") — solo es mucho más lento para un primer índice completo.

  • Un iPhone. Todo lo del lado del teléfono es la aplicación Atajos integrada más una PWA en la pantalla de inicio; sin aplicación que instalar, sin emparejamiento, sin jailbreak.

Instalación

git clone <this repo>
cd mobile_claude_connect

# CUDA build of torch first, if you have an NVIDIA GPU:
pip install torch --index-url https://download.pytorch.org/whl/cu128

pip install -r requirements.txt

# Browser engine for the capability plugins. Separate step - pip does not do this.
playwright install chromium

Si tienes Google Chrome instalado, caps.launch_kwargs() lo usará (channel="chrome") con preferencia sobre el Chromium incluido, y playwright install chromium se vuelve opcional.

Configuración

copy config.example.json config.json
python -c "import secrets; print(secrets.token_urlsafe(24))"

Edita config.json:

  • token — pega el secreto generado. El teléfono necesita el mismo valor.

  • vault_dir — ruta absoluta donde aterrizan las subidas del teléfono.

  • watch_dirs — carpetas escaneadas para fotos en su lugar (no se copia nada). Apunta esto a tu biblioteca de iCloud para Windows, p. ej. C:\Users\YOUR_USERNAME\Pictures\iCloud Photos\Photos.

  • devicecuda o cpu.

Ejecutar sin un config.json sale con instrucciones en lugar de un traceback.

Cortafuegos

# Run as Administrator
powershell -ExecutionPolicy Bypass -File open_firewall.ps1

Esto abre TCP 8778 solo a 100.64.0.0/10 e imprime la URL para abrir en el teléfono. Mantén los archivos .ps1 solo ASCII: Windows PowerShell 5.1 los lee en la página de códigos ANSI del sistema, y los caracteres no ASCII se corromperán.

Ejecución

Haz doble clic en run_bridge.bat (o python server.py). Cerrar la ventana detiene el puente, y nada funciona desde el teléfono mientras esté caído.

Con el puente activo, el índice se mantiene solo: cada auto_index_minutes (por defecto 15) el servidor lanza indexer.py como un subproceso de corta duración, de modo que los ~2 GB de VRAM de CLIP se devuelven entre ejecuciones en lugar de mantenerse mientras el servidor viva. Una pasada inactiva solo hace estadísticas del árbol de archivos y nunca toca la GPU. La salida va a autoindex.log.

Para una primera importación masiva, python backfill.py recorre escaneo y embedding hasta que la carpeta de origen deja de crecer — útil mientras iCloud aún está descargando una biblioteca grande. No lo ejecutes al mismo tiempo que el auto-indexado; dos procesos CLIP pelearán por la VRAM.

Registrar el servidor MCP

claude mcp add phone -s user -- python C:\path\to\mobile_claude_connect\mcp_server.py

Trampa: los servidores MCP se cargan cuando comienza una sesión. Un servidor añadido con claude mcp add no aparecerá en la sesión en la que estás actualmente. Inicia una nueva sesión.

La configuración del lado del teléfono — la PWA, la importación masiva de fotos y las recetas de Shortcut — está en SETUP.md.

Uso

Desde una sesión de Claude Code en el PC (incluida una que estés manejando desde el teléfono mediante el Control Remoto de la app de Claude):

Find the photos from my trip three years ago that show a pump machine.

Lo que ocurre: photos_stats para comprobar la cobertura → photos_places para encontrar dónde estuviste realmente y cuándo → photos_search("a pump machine", date_from=..., date_to=...) para clasificar candidatos → photos_open en los mejores resultados → Claude mira los JPEG y responde desde lo que ve. CLIP reduce; Claude juzga.

Las consultas en coreano (o cualquier idioma no inglés) se traducen a una frase corta en inglés antes de la búsqueda, porque el codificador de texto de CLIP es solo inglés.


Lo que no está incluido

Este repositorio es solo código. Todo lo que hizo útil la instancia en ejecución son datos personales y no están aquí:

  • bridge.db — el índice de fotos. Comienzas con un índice vacío. Apunta watch_dirs a una carpeta de fotos y ejecuta python indexer.py (o deja que el auto-indexado lo haga) para construir el tuyo. La primera ejecución descarga el modelo CLIP, alrededor de 1.7 GB.

  • vault/ — fotos subidas, videos y elementos soltados desde la hoja de compartir.

  • preview/ — JPEGs renderizados por photos_open.

  • profiles/ — perfiles de navegador de Playwright, es decir, sesiones activas con inicio de sesión. Tú inicias sesión tú mismo, una vez por servicio, mediante capability_login.

  • config.json — contiene el token de portador. Copia config.example.json.

Todos estos están en .gitignore. Mantenlos ahí.

Limitaciones conocidas

  • El historial de llamadas y los SMS no se pueden recuperar. iOS no expone ninguna API para ninguno de los dos, a ninguna app. Una app nativa no ayudaría; la única vía es la extracción de la copia de seguridad local, que necesita emparejamiento de bloqueo.

  • El PC debe estar encendido. El teléfono es una pantalla, no un par.

  • El espejo /login es JPEG de ~3 fps a 1366×900 — suficiente para un formulario de inicio de sesión, no para navegar.

  • La interfaz PWA del lado del teléfono está en coreano (static/index.html, static/login.html). El servidor, las herramientas MCP y todo lo que Claude lee están en inglés.

Licencia

Este es un repositorio solo de código. El código aquí es MIT — ver LICENSE — y es lo único que este repo realmente distribuye. Todo lo demás llega a tu máquina desde algún otro lugar: pip install -r requirements.txt extrae las ruedas de PyPI, los pesos de CLIP vienen de Hugging Face, y el navegador viene de playwright install. No se redistribuye ningún binario de terceros aquí. Las obligaciones de copyleft se adjuntan a la redistribución, así que para el caso ordinario — clonarlo, instalarlo, ejecutarlo en tu propio PC — casi nada de lo siguiente es algo que tengas que hacer, y el resto está escrito para el día en que empaques esto en algo que entregues a otra persona.

Ejecutar desde el código fuente (lo que casi todos hacen)

Nada que cumplir. Las licencias permisivas en la tabla solo piden que los avisos sobrevivan si copias código de una dependencia a tu propio proyecto. Dos cosas aún valen la pena saber antes de hacer planes, y ninguna de ellas es una cuestión de copyleft.

Los pesos de CLIP no tienen licencia, y eso no es lo mismo que ser permisivo. Este es el único elemento aquí que puede afectar lo que haces con la cosa mientras simplemente la ejecutas. La biblioteca transformers es Apache-2.0, pero los pesos son un artefacto separado con términos separados. El repositorio de Hugging Face openai/clip-vit-large-patch14 no contiene ningún archivo LICENSE y no declara ningún campo license en los metadatos de su tarjeta de modelo. El repositorio de código openai/CLIP aguas arriba es MIT (© 2021 OpenAI), pero ese texto de licencia cubre el código en ese repositorio y no dice nada sobre los checkpoints. Así que: si el uso comercial de estos pesos está permitido no está verificado. La tarjeta del modelo también declara su propia posición claramente — "Cualquier caso de uso desplegado del modelo — ya sea comercial o no — está actualmente fuera de alcance", con el modelo destinado a la investigación sobre robustez y generalización, y la vigilancia y el reconocimiento facial nombrados como permanentemente fuera de alcance. Esa es la intención declarada de los autores más que una concesión o prohibición de licencia, pero si estás decidiendo si construir un producto sobre esto, es lo más directo que han dicho. Cambiar clip_model por un modelo con metadatos de licencia explícitos (existen varias variantes de CLIP con licencia abierta) es la salida limpia.

Automatizar un sitio de terceros se rige por los términos de ese sitio, no por esta licencia. Los plugins de capacidad manejan sesiones web con inicio de sesión — naver_mail.py es el ejemplo incluido, y los siguientes obvios (Coupang Eats, Gmail) tienen la misma forma. Si puedes scriptear una cuenta que posees es una cuestión de los términos de uso de ese servicio y cualquier ley de acceso a computadoras aplicable; la licencia MIT sobre este código no te otorga nada allí. Lo mismo aplica para cualquier servidor MCP de terceros que registres junto a este: lleva su propia licencia y sus propios términos de servicio.

Licencias de dependencias

La pila es mayormente permisiva, pero dos de las ruedas incluyen binarios copyleft, una incluye bibliotecas propietarias de NVIDIA, y un componente no tiene ninguna licencia declarada. Cada "ver abajo" en la columna derecha es una obligación de redistribución, no una de tiempo de ejecución.

Dependencia

Licencia (SPDX)

Qué te obliga a hacer

mcp (Model Context Protocol Python SDK)

MIT

Conservar el aviso.

Flask, y su cadena Werkzeug / Jinja2 / Click / itsdangerous / MarkupSafe / Blinker

BSD-3-Clause en toda la cadena, excepto Blinker que es MIT

Conservar el aviso.

waitress

ZPL-2.1

Conservar el aviso; marcar cualquier archivo que modifiques como modificado (cláusula ZPL 2); la licencia no otorga derechos de marca.

NumPy

BSD-3-Clause (expresión completa BSD-3-Clause AND 0BSD AND MIT AND Zlib AND CC0-1.0 para el código incluido)

Conservar el aviso. Sus ruedas también incluyen OpenBLAS, y en Linux libgfortran (GPL-3.0-or-later CON GCC-exception-3.1, que es lo que impide que llegue a tu código) y libquadmath (LGPL-2.1-or-later).

transformers, huggingface_hub, tokenizers, safetensors

Apache-2.0

Conservar el aviso y el archivo NOTICE; Apache-2.0 también te obliga a indicar los cambios significativos.

PyTorch

BSD-3-Clause — pero una rueda CUDA también incluye el runtime CUDA y cuDNN de NVIDIA, declarados como LicenseRef-NVIDIA-Proprietary

Ver más abajo. Esos componentes son propietarios, no BSD.

pillow-heif

Código fuente BSD-3-Clause, pero las ruedas incluyen libheif y libde265 (LGPL-3.0) y x265 (GPL-2.0)

Ver más abajo. PyPI clasifica el paquete en sí como GPLv2 por esta razón.

PyAV (av)

Enlace BSD-3-Clause; el núcleo FFmpeg de la rueda es LGPL-3.0-or-later, pero la rueda también incluye x264 y x265 (GPL-2.0-or-later)

Ver más abajo.

Playwright

Apache-2.0 — pero en x64 el navegador que descarga no es Chromium de código abierto

Ver más abajo.

Pesos de CLIP, openai/clip-vit-large-patch14

Sin licencia declarada en el artefacto que descargas

Ver más arriba — la única incógnita real, y la única que importa en tiempo de ejecución.

Si compilas y redistribuyes un binario

Empaquetar esto en un instalador, una imagen Docker o cualquier otro artefacto que entregues a otra persona es lo que convierte lo marcado más arriba en obligaciones reales.

La rueda de PyAV es FFmpeg LGPL con codificadores GPL a su lado — la distinción es más sutil de lo que parece. FFmpeg es LGPL-2.1-or-later por defecto y pasa a GPL cuando se compila con --enable-gpl, que es lo que upstream exige para x264 y x265. Las ruedas de PyAV no se compilan con esa opción: el avutil incluido reporta libavutil license: LGPL version 3 or later y su línea de configuración muestra --enable-version3 --enable-libx264 --enable-libx265 sin --enable-gpl. Esto es posible porque PyAV modifica el configure de FFmpeg para mover x264 y x265 de la lista GPL a la lista version-3. Por tanto, el núcleo de FFmpeg es LGPL-3.0-or-later — pero x264 y x265 son en sí mismos GPL-2.0-or-later, y av.libs/ los incluye como libx264-165.dll y libx265.dll. Así que pip install av sigue metiendo código GPL en tu grafo de dependencias, diga lo que diga el propio FFmpeg. Este proyecto solo lee duración, rotación y fotogramas de muestra y nunca toca un codificador, así que la solución práctica si redistribuyes es eliminar esos dos DLL, o compilar desde el sdist (pip install --no-binary av av) contra tu propio FFmpeg. Otras dos diferencias menores que conviene conocer: el directorio licenses/ de la rueda solo contiene el texto BSD-3-Clause de PyAV y ninguno de los avisos de FFmpeg, x264 o x265, y delvewheel renombra los DLL de FFmpeg con sufijos hash, lo que contradice la propia lista de verificación de cumplimiento de FFmpeg.

pillow-heif tiene la misma forma, más un problema de patentes. Su código Python es BSD-3-Clause, pero la rueda binaria incluye libheif y libde265 bajo LGPL-3.0 y el codificador x265 bajo GPL-2.0 — por eso su clasificador en PyPI dice "GNU General Public License v2" aunque su campo de licencia declarado sea BSD-3-Clause. Este proyecto solo decodifica HEIC desde el teléfono, así que el codificador GPL nunca se invoca, pero sigue estando en la rueda. Y de forma separada e independiente del copyright: HEVC/H.265, el códec que hay dentro de HEIC, está cubierto por grupos de patentes cuyos administradores afirman que los productos con codificación o decodificación HEVC normalmente necesitan una licencia. Eso es un asunto de patentes, no de licencias de software, y va dirigido a productos que distribuyen decodificadores comercialmente — un servidor personal no es el objetivo — pero es una obligación real que ninguna licencia de código abierto resuelve por ti.

Playwright es Apache-2.0, y en x64 el navegador que descarga no es Chromium de código abierto. El código fuente de Chromium es BSD-3-Clause con un gran conjunto de licencias de terceros (Blink bajo BSD/LGPL, código derivado de Mozilla bajo MPL/GPL/LGPL, y varios cientos más, agregados en chrome://credits). Pero playwright install chromium ya no descarga eso en x64. El browsers.json de Playwright nombra la descarga "Chrome for Testing", y cdn.playwright.dev redirige al propio bucket chrome-for-testing-public de Google. El artefacto está compilado y con la marca de Google, e incluye el Widevine CDM, cuya licencia establece claramente que "no es software de código abierto" y que no puede distribuirse sin un acuerdo separado con Google. Solo la compilación para linux-arm64 sigue siendo Chromium propio de Playwright. La documentación pública de Playwright sigue describiendo la opción por defecto como Chromium de código abierto; el código distribuido dice otra cosa. Y aparte, caps.launch_kwargs() prefiere channel="chrome" — tu Google Chrome real instalado, sujeto a los Términos del Servicio de Google Chrome y no a ninguna licencia de código abierto. La conclusión para la redistribución: no incluyas ninguno de los dos. Deja que el usuario instale su propio navegador, que es lo que este repositorio ya hace. Sin verificar: si Google exime a Chrome for Testing de los términos de consumo de Chrome.

Una compilación CUDA de PyTorch no es puramente BSD. PyTorch en sí es BSD-3-Clause, pero la rueda CUDA que recomienda el paso de instalación de este README — la de download.pytorch.org/whl/cu128, no la de PyPI, cuya rueda para Windows es solo CPU — incluye el runtime CUDA de NVIDIA y los binarios de cuDNN. Al inspeccionar un torch ...+cu128 instalado se ven 22 de ellos en torch/lib (cuBLAS, cuDNN, cuFFT, cuRAND, cuSOLVER, cuSPARSE y compañía). Los metadatos de su rueda declaran LicenseRef-NVIDIA-Proprietary, y la EULA de CUDA permite redistribuir el runtime solo bajo sus propias condiciones: tu aplicación debe añadir funcionalidad material, los binarios no deben modificarse, deben ser accesibles solo por tu aplicación, y no puedes usar el SDK de forma que quede sujeto a una licencia de código abierto. cuDNN añade un suplemento que prevalece sobre los términos base cuando entran en conflicto. Nada de eso es BSD. La ejecución local no se ve afectada por nada de esto; la rueda solo CPU evita la cuestión por completo.

Nada de esto es asesoramiento legal.

A
license - permissive license
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI services like Claude and Cursor to remotely control a Mac by executing shell commands, managing files, and running AppleScript for UI automation. Access is secured through OAuth 2.0 authentication and encrypted tunnels to protect remote interactions.
    2
    MIT
  • A
    license
    B
    quality
    A
    maintenance
    Enables Claude to interact with Apple apps on macOS including Mail, Calendar, Contacts, Reminders, Notes, and iCloud Drive for personal productivity tasks like triaging email, managing calendar, and cross-app context.
    76
    5
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables Claude to access and search local messages and contacts across multiple platforms (iMessage, Discord, Gmail, Slack) via a local-first datastore, ensuring data never leaves the Mac.
    MIT

View all related MCP servers

Related MCP Connectors

  • Let ChatGPT, Claude & Cursor use your Mac: email, calendar, iMessage, Teams, files. Local, free.

  • Search, read, and write your Apple Notes from ChatGPT/Claude via a local Mac agent + MCP relay.

  • MCP connector for iMessage & Contacts via a local Mac agent + Vercel relay

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/riseblyp/mobile_claude_connect'

If you have feedback or need assistance with the MCP directory API, please join our Discord server