Metadata-Version: 2.5
Name: ghl-pro-mcp
Version: 0.2.5
Summary: Le das una orden en tu idioma y monta el embudo entero en GoHighLevel: brief, investigación de mercado, y despliegue de etiquetas, campos, pipeline, landing y workflow.
License: Proprietary
Keywords: automation,crm,funnels,gohighlevel,mcp,model-context-protocol,workflows
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business
Classifier: Topic :: Office/Business :: Scheduling
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: mcp<3,>=2
Requires-Dist: platformdirs>=4
Requires-Dist: tzdata>=2024.1
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# ghl-pro-mcp

**Le das una orden en tu idioma y te monta el embudo entero dentro de GoHighLevel.**

> «Quiero un embudo para mi clínica de mascotas, y que agende citas»

A partir de ahí, el asistente **pregunta lo que le falta** —no inventa nada—, investiga
el mercado de tu zona, y despliega en tu cuenta: etiquetas, campos personalizados,
pipeline con sus etapas, landing con formulario real y el workflow de respuesta y
seguimiento. Todo queda en **borrador**, y se puede **deshacer** de una pieza.

Esto es un **servidor MCP local**: funciona con Claude Code, Claude Desktop, Codex,
Cursor, Cline, Windsurf o VS Code. Corre **en tu ordenador** — tus credenciales y los
datos de tu CRM no pasan por ningún servidor intermedio.

---

## Por qué este y no otro

| | MCP oficial de GHL | Este |
|---|---|---|
| Leer workflows | Sí | Sí |
| **Crear y guardar workflows** | **No** | **Sí** |
| **Crear embudos** | **No** | **Sí** |
| **Guardar y publicar páginas** | **No** | **Sí** |
| **Crear y editar surveys** | **No** | **Sí** |
| Operaciones de la API pública disponibles | 548 | 548 |

No es una opinión: la API pública de GoHighLevel **solo permite leer** workflows, embudos,
páginas y surveys. Es un muro de su API, no de su configuración. Cualquier integración que
se apoye solo en la API pública se queda fuera de ahí — y ahí es donde está el trabajo.

Este servidor usa además la **vía de sesión** para esas cuatro cosas, que es lo que le deja
montar el embudo completo en lugar de limitarse a consultarlo.

---

## El flujo, de principio a fin

```
«quiero un embudo para mi clínica de mascotas»
        │
        ├─ nuevo_proyecto ──────► crea el brief y devuelve las preguntas
        │
        ├─ responder_brief ─────► se contestan (el asistente pregunta lo que falta)
        │
        ├─ guia_de_investigacion ► qué hay que averiguar del mercado de esa zona
        ├─ guardar_investigacion ► 3-5 competidores y las palabras que usa su cliente
        │
        ├─ ver_plan_despliegue ──► enseña qué va a crear y qué falta
        │
        ├─ desplegar_plan ───────► LO CREA TODO, en borrador
        │
        └─ ver_manifiesto ───────► qué se creó, para poder deshacerlo
              deshacer_plan ─────► borra lo que creó, y dice lo que no pudo
```

**El brief manda.** Sin las respuestas críticas —sector, objetivo, oferta, zona, quién
atiende y qué es un buen lead— el despliegue **no se ejecuta**. Y sin la investigación del
mercado tampoco: sin las palabras que usa tu cliente, la landing sale con los tópicos del
sector, igual que la de cualquier competidor.

### Qué crea el despliegue

1. **Etiquetas** de segmentación, según lo que el negocio necesite
2. **Campos personalizados** — los que tú digas: la fecha de la última visita, la talla,
   lo que haga falta para el seguimiento. **Sin esto no hay recordatorio del próximo
   servicio**, que es la táctica que más dinero devuelve cuando se vende varias veces al
   mismo cliente
3. **Pipeline** con etapas derivadas del objetivo (no las mismas cinco para todos)
4. **Landing** con formulario nativo de GoHighLevel — se comprueba que capte de verdad
5. **Workflow**: crea la oportunidad en el pipeline, responde al cliente por el canal que
   tenga, avisa al negocio, espera un día y deja una tarea de repaso

**Nada se publica.** Los workflows quedan en borrador y la landing sin publicar: publicar
es tu decisión.

**Nada se duplica.** Si despliegas dos veces, reutiliza lo que se llame igual y te dice
qué revisar. Y lo que ya tenías **no se apunta** en el manifiesto, así que deshacer no te
borra algo tuyo.

---

## Requisitos

- **uv** (recomendado), o Python **3.10** o superior.
- Una **Private Integration Token** de GoHighLevel, creada dentro de la subcuenta que
  quieras conectar y con los *scopes* que necesites.

---

## Instalación

**No hay que instalar nada a mano.** Con `uv` en el equipo, el cliente MCP se lo baja de
PyPI la primera vez que lo usa:

```json
{
  "mcpServers": {
    "ghl-pro": {
      "command": "uvx",
      "args": ["--refresh-package", "ghl-pro-mcp", "ghl-pro-mcp@latest"],
      "env": { "GHL_ENABLE_SESSION": "1" }
    }
  }
}
```

Es el equivalente a `npx`. El `@latest` comprueba si hay versión nueva cada vez, así que
los arreglos llegan solos.

> **En el cliente va `--refresh-package`, no `--refresh` a secas.** `--refresh` refresca
> **toda** la caché en **cada arranque**, y con el tiempo de arranque corto que traen algunos
> clientes el servidor no levanta. `--refresh-package` refresca **solo este paquete**, tarda lo
> mismo y garantiza la última versión. `--refresh` a secas es **solo para los comandos de
> terminal**, que es donde no hay timeout de cliente y se quiere forzar la última versión.

Y **las credenciales nunca van en este archivo**: el servidor las lee de `credentials.env`.
El `env` lleva solo `GHL_ENABLE_SESSION`. El detalle, en «Añádelo a tu cliente».

### Los comandos de terminal

El cliente se lo baja solo con `uvx`, así que **no hace falta instalar nada** — pero los
comandos de configuración y diagnóstico (`setup`, `doctor`) se lanzan igual, con `uvx`
delante, y ahí **sí** con `--refresh`:

```powershell
uvx --refresh ghl-pro-mcp@latest --version     # comprobar que arranca
uvx --refresh ghl-pro-mcp@latest setup         # configurar
uvx --refresh ghl-pro-mcp@latest doctor        # comprobar contra tu GoHighLevel
```

> **Si lo instalas como herramienta** (`uv tool install ghl-pro-mcp`), el `uvx` sobra y
> los comandos quedan como `ghl-pro-mcp setup` y `ghl-pro-mcp doctor`. Las dos vías valen;
> `uvx` no deja nada instalado.

Funciona igual en **Windows, macOS y Linux**.

### Varias subcuentas: `perfil`

Si trabajas con más de una subcuenta de GoHighLevel, **cada cuenta se añade desde la
terminal, una sola vez**, con las credenciales fuera del chat:

```powershell
uvx --refresh ghl-pro-mcp@latest perfil nuevo                  # pregunta todo, paso a paso
uvx --refresh ghl-pro-mcp@latest perfil nuevo clinica-dental-daniela
uvx --refresh ghl-pro-mcp@latest perfil listar                 # cuáles hay y cuál está activo
uvx --refresh ghl-pro-mcp@latest perfil usar clinica-dental-daniela
uvx --refresh ghl-pro-mcp@latest perfil borrar clinica-dental-daniela
```

`perfil nuevo` pide el **nombre**, el **Location ID** y el **Private Integration Token**
(validados contra GoHighLevel real) y después la parte de workflows y embudos, igual que
`setup`. Lo deja **activo**. `listar`, `usar` y `borrar` gestionan los que ya tienes;
`borrar` pide confirmación y, si era el activo, vuelve a la cuenta principal.

**Las credenciales nunca se pegan en el chat de la IA ni van como argumento del comando**
(quedarían en el historial del shell). Y **para cambiar de cuenta no hace falta terminal**: se
le dice a la IA «cámbiate a la cuenta `<nombre>`» o «vuelve a la cuenta principal», que es lo
que hace `cambiar_perfil`.

---

## Configuración

**Un solo comando:**

```powershell
uvx --refresh ghl-pro-mcp@latest setup
```

Te pide el token privado y el Location ID —y **te confirma el nombre de la subcuenta**
antes de guardar nada—, y después te ofrece configurar workflows y embudos: con la
extensión de Chrome, a mano, o dejarlo para más tarde.

> **Hazlo en una terminal, nunca desde el chat de la IA.** Lo que se escribe en la
> conversación acaba en el historial, y el token privado da acceso completo al CRM.

Las credenciales quedan en un único archivo, en tu carpeta de usuario:

| Sistema | Ruta |
|---|---|
| Windows | `%LOCALAPPDATA%\ghl-pro-mcp\credentials.env` |
| macOS | `~/Library/Application Support/ghl-pro-mcp/credentials.env` |
| Linux | `~/.config/ghl-pro-mcp/credentials.env` |

Si prefieres decidir tú la ubicación, define `GHL_PRO_ENV_PATH` y el asistente escribirá
ahí: respeta esa variable, igual que el servidor al leer.

---

## Añádelo a tu cliente

Al terminar, `setup` te muestra el bloque exacto que necesitas. Es el de arriba.

`GHL_ENABLE_SESSION` enciende **workflows, embudos y páginas**. Sin esa línea tendrás las
548 operaciones de la API pública, pero no el extra — y ese extra es la diferencia.

**Reinicia tu cliente de IA** después de añadirlo.

| Cliente | Dónde va |
|---|---|
| **Claude Code** | `.mcp.json` en la raíz de tu proyecto |
| **Claude Desktop** | `%APPDATA%\Claude\claude_desktop_config.json` (Windows) · `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) · `~/.config/Claude/claude_desktop_config.json` (Linux) |
| **Cursor, Cline, Windsurf** | Su propio archivo de configuración de MCP |

**Codex usa TOML** (`~/.codex/config.toml`), y ahí `startup_timeout_sec = 60` no sobra: Codex
no le pone tiempo de arranque y la primera vez hay que descargar el paquete de PyPI.

```toml
[mcp_servers.ghl-pro]
command = "uvx"
args = ["--refresh-package", "ghl-pro-mcp", "ghl-pro-mcp@latest"]
# Codex da un tiempo máximo de arranque al servidor MCP.
startup_timeout_sec = 60
env = { GHL_ENABLE_SESSION = "1" }
```

> ### 🔒 Las credenciales no van en este archivo
>
> El archivo de configuración del cliente solo dice **cómo arrancar** el servidor. El token
> `pit-…`, el Location ID, el refresh token y la API key van **solo** en `credentials.env`,
> que ya tiene lo del paso de configuración.
>
> **El error que se ve mucho** es meterlos en el `env`, y eso deja el token en texto plano en
> el disco:
>
> ```json
> "env": { "GHL_ENABLE_SESSION": "1", "GHL_PRIVATE_TOKEN": "pit-…", "GHL_LOCATION_ID": "…" }
> ```
>
> ❌ **Así no.** El `env` lleva **solo** `GHL_ENABLE_SESSION`.
>
> **Y la IA nunca debe pedirte las credenciales por el chat.** Si te las pide, no se las des:
> se configuran con `uvx --refresh ghl-pro-mcp@latest setup`, en una terminal.

> Hace falta `uv`: `winget install astral-sh.uv`, o
> `curl -LsSf https://astral.sh/uv/install.sh | sh`.

---

## Comprobar que funciona

```powershell
uvx --refresh ghl-pro-mcp@latest doctor
```

Comprueba la configuración contra tu GoHighLevel real y te dice, una a una, qué funciona
y qué no. **No modifica nada** salvo que se lo pidas expresamente. Y si quieres llegar más
lejos, tiene dos banderas que sí escriben, pero que **dejan todo como estaba**:

```powershell
uvx --refresh ghl-pro-mcp@latest doctor --escritura          # crea un workflow de prueba y LO BORRA
uvx --refresh ghl-pro-mcp@latest doctor --pagina <pageId>    # guarda esa página sin cambiarla
```

---

## Las 92 herramientas

### El flujo — de la orden al embudo montado

| Herramienta | Qué hace |
|---|---|
| `disenar_automatizacion` | Empieza: convierte una idea vaga en un plan por etapas (captura, calificación, conversión, atención, seguimiento, métricas) |
| `nuevo_proyecto` | Después del diseño: crea el brief y devuelve las preguntas que hay que hacer |
| `responder_brief` | Guarda las respuestas (fusiona, nunca borra lo ya contestado) |
| `ver_brief` | Cómo va, qué falta, y cuál es el siguiente paso |
| `listar_proyectos` | Los proyectos empezados y a cuáles les falta información |
| `guia_de_investigacion` | Qué hay que averiguar del mercado de esa zona, y por qué |
| `guardar_investigacion` | Guarda competidores, palabras del cliente, objeciones y precios |
| `ver_plan_despliegue` | Qué va a crear, en qué orden y qué falta |
| `desplegar_plan` | **Lo crea todo**, en borrador |
| `ver_manifiesto` | Qué se creó y con qué id |
| `deshacer_plan` | Borra lo que creó, y dice lo que no se pudo borrar |

### Cuenta y conocimiento

| Herramienta | Qué hace |
|---|---|
| `get_account_context` | Subcuenta, pipelines con etapas, calendarios y usuarios |
| `list_playbooks` | Índice de los 22 documentos de conocimiento |
| `get_playbook` | Devuelve un documento entero, o una sección suya |

### Workflows — el foso

| Herramienta | Qué hace |
|---|---|
| `catalogo_acciones` | Qué acciones puede tener un workflow |
| `listar_workflows` · `ver_workflow` | Listar y leer, con sus nodos |
| `ver_triggers` | Los disparadores de un workflow, con sus filtros |
| `crear_workflow` · `guardar_workflow` | Crear y guardar las acciones |
| `crear_trigger` · `actualizar_trigger` | Crear un disparador y cambiar sus filtros |
| `catalogo_triggers` | **Todos** los disparadores que admite GoHighLevel |
| `crear_carpeta` · `listar_carpetas` · `borrar_carpeta` | Carpetas de formularios, surveys y plantillas de email |
| `crear_plantilla_email` | Crea una plantilla de email y la mete en su carpeta |
| `asistente_de_workflows` | Pedirle el workflow a la IA nativa, **y ver sus preguntas** |
| `publicar_workflow` · `despublicar_workflow` | Encender y apagar |
| `borrar_workflow` · `borrar_workflows_por_nombre` | Borrar |

**Las 89 acciones y los 83 disparadores están en el código, no en un documento.**
`catalogo_acciones` y `catalogo_triggers` los listan, y el servidor construye el JSON interno
por ti: nunca escribes `next`, `parentKey` ni el `attributes` de un nodo — equivocarse en uno de
esos nombres guarda el workflow con 200 y deja el paso en blanco, sin ningún error.

**Y hay un atajo: la IA nativa de GoHighLevel.** `asistente_de_workflows` le pide un workflow en
lenguaje natural y devuelve sus pasos propuestos y —esto es lo importante— **las preguntas que
hace cuando le falta un dato**. Esas preguntas no vienen en el texto: viajan en un evento aparte
del flujo, así que leer solo la respuesta parecería que no ha contestado nada. Con las respuestas,
el workflow se monta con `crear_trigger` + `guardar_workflow` (el asistente propone; quien deja
el workflow en la cuenta y en borrador es el servidor).

### Embudos y páginas — el foso

| Herramienta | Qué hace |
|---|---|
| `listar_embudos` · `ver_pagina` | Listar y leer |
| `crear_embudo` · `crear_paso` | Crear la estructura |
| `guardar_pagina` | Guardar el contenido de una página |
| `generar_landing_con_ia` | Pedirle la landing a la IA de GoHighLevel, con tu copy |
| **`ver_landing`** | **Devuelve una FOTO de la página**, para que el modelo la mire |
| **`insertar_survey_en_pagina`** | Meter una encuesta dentro de la página |
| `publicar_pagina` | Publicar (necesita dominio) |

**`ver_landing` es la que cambia el trabajo.** El contenido de una página dice qué elementos
hay, **no cómo quedan**: un texto gris sobre fondo oscuro está perfecto en el dato y es
ilegible en la pantalla. Con la foto, el modelo lo ve y lo corrige.

### El sistema experto de diseño

Cuando le pides una landing a la IA de GoHighLevel, **no va sola**: el prompt llega con la
identidad visual del negocio ya resuelta.

```
El negocio  →  una de 13 FAMILIAS estéticas  →  su PALETA, con los hex
                                              →  la ESTRUCTURA de secciones
                                              →  las reglas de composición y copy
```

**Clasifica por familia estética, no por sector** — por eso vale para cualquier negocio: la
misma paleta sirve para una veterinaria y para un fisioterapeuta. Y si el negocio no encaja
en ninguna, usa una genérica limpia que no desentona.

**Verificado contra GoHighLevel real:** una clínica veterinaria salió con el fondo crema
`#FAFAF7` y el botón verde salvia `#7C9082` — la paleta que le tocaba, con el color
apareciendo 50 veces en la página — y con el nombre correcto.

**Y si la familia no le pega, se cambia con una palabra:** `familia_diseno`. El clasificador
acierta casi siempre, pero no es infalible — una palabra larga y genérica puede ganar a la
del sector. Eso está documentado en vez de escondido.

**Y ojo con los estilos.** Los genera el **editor** de GoHighLevel, no la API. Si cambias
**textos, precios o imágenes**, la página sigue perfecta (el CSS viaja con el contenido). Si
cambias **colores o tamaños** por API, el CSS se queda describiendo el estilo viejo y la
página sale plana. Detalle en [`docs/paginas-css.md`](docs/paginas-css.md).

### Surveys — el foso

Un formulario **recoge datos**; un survey **califica**. El que no encaja se descarta solo, y
el que llega a la llamada ya viene caliente y con sus respuestas escritas. La API pública
solo puede *leer* surveys, así que esto tampoco está en el MCP oficial.

| Herramienta | Qué hace |
|---|---|
| `crear_survey` | **Todo en un paso**: los campos, las preguntas, los descartes y los textos finales |
| `listar_surveys` · `ver_survey` | Listar, leer, y **decir qué tiene mal** |
| `guardar_survey` | Guardar uno ya editado — **se niega si perdería preguntas o textos** |
| `respuestas_de_survey` | Las respuestas, por contacto y por pregunta |
| `borrar_survey` | Borrar (pide confirmación: se lleva también las respuestas) |

Se diseña así, y no es adorno: **una pregunta por pantalla** (diez juntas no las contesta
nadie), **la primera fácil**, **los descartes repartidos** —tres seguidos parecen un
interrogatorio— y **una pregunta abierta, penúltima y sin obligar**: es la que dice qué
quiere aprender el lead, con sus palabras.

### Contactos, CRM y agenda

| Herramienta | Qué hace |
|---|---|
| `search_contacts` · `create_contact` | Buscar y crear contactos |
| `list_tags` · `ensure_tags` | Etiquetas: listar y crear solo las que falten |
| `list_pipelines` · `ver_pipeline` · `crear_pipeline` · `borrar_pipeline` | Pipelines |
| `ver_etapas_del_pipeline` | Las etapas, en orden |
| `crear_oportunidad` · `mover_oportunidad` · `buscar_oportunidades` | El lead en el tablero |
| `listar_calendarios` · `ver_huecos_libres` · `agendar_cita` · `ver_citas_de_contacto` | Calendario y citas |
| `listar_campos_personalizados` · `crear_campos_personalizados` | Los campos del seguimiento |

### Mensajes y archivos

| Herramienta | Qué hace |
|---|---|
| `enviar_email` · `enviar_sms` | Enviar, **pasando antes por el checklist de copy** |
| `estado_de_email` | Comprobar si llegó |
| `listar_archivos` · `subir_archivo` · `borrar_archivo` | Archivos |
| `listar_caller_ids` | Números verificados |

### El resto del catálogo

| Herramienta | Qué hace |
|---|---|
| `estado_catalogo` | Cuántas operaciones hay y de qué dominios |
| `buscar_operaciones` · `describir_operacion` · `llamar_operacion` | Cualquiera de las 548 operaciones de la API pública |
| `estado_sesion` | Si la vía de sesión está encendida |

---

## Las escrituras empiezan en seco

**Ninguna herramienta escribe a la primera.** Unas usan `dry_run=true` —la primera llamada
enseña lo que haría y no crea nada— y otras usan `confirmar=true`. En cualquiera de los dos
casos, **nada se crea ni se envía sin que lo hayas pedido expresamente**.

Y hay reglas que están **en el código**, no en un documento:

- **El copy se revisa antes de enviar o guardar.** Un SMS con un hueco sin rellenar, o con
  urgencia inventada, no sale.
- **No se manda SMS sin que lo hayas elegido.** Cuesta dinero por mensaje y exige
  consentimiento.
- **Los workflows nacen en borrador** y la landing sin publicar.

---

## Lo que todavía NO hace

Preferimos decirlo:

- **Recordatorio de cita, petición de reseña y reactivación.** El **disparador de cita ya
  está verificado** (se reservó una cita real y el workflow disparó en 5 segundos), así que
  se pueden montar hoy con `crear_trigger` + `guardar_workflow`; lo que falta es que el plan
  los despliegue solo.
- **WhatsApp.** Fuera de las 24 horas siguientes al último mensaje del cliente, WhatsApp
  solo admite plantillas aprobadas por Meta. No se pueden inventar.
- **Retomar una petición al asistente de IA.** Se le puede pedir un workflow y se ven sus
  preguntas y su propuesta (`asistente_de_workflows`). Pero **si se queda preguntando, ese
  workflow queda bloqueado** (`RUN_CONFLICT`) hasta descartar la solicitud pendiente en el
  editor de GoHighLevel: ese descarte no está expuesto por API.
- **Publicar una página** necesita un dominio en la cuenta.

---

## Dónde se guarda cada cosa

| Qué | Dónde |
|---|---|
| El programa | Dentro del paquete instalado (solo lectura) |
| Tus preferencias, briefs y manifiestos | Directorio de configuración del sistema |
| Tus credenciales | Donde tú decidas, vía `GHL_PRO_ENV_PATH` |

| Sistema | Preferencias |
|---|---|
| Windows | `%LOCALAPPDATA%\ghl-pro-mcp` |
| macOS | `~/Library/Application Support/ghl-pro-mcp` |
| Linux | `~/.config/ghl-pro-mcp` |

---

## Diagnóstico

El servidor **nunca escribe en `stdout`** salvo el protocolo: todos los logs van a
`stderr`. Si algo falla, sube el detalle con:

```bash
GHL_PRO_LOG_LEVEL=DEBUG uvx ghl-pro-mcp
```

Errores frecuentes:

| Síntoma | Causa |
|---|---|
| «Falta configuración: GHL_PRIVATE_TOKEN» | No definiste la variable o el archivo |
| «GHL_PRO_ENV_PATH apunta a un archivo que no existe» | Ruta mal escrita |
| 401 al llamar | El token caducó o se revocó |
| 403 al llamar | Al token le falta el *scope* de esa operación |
| Faltan datos del catálogo | El paquete se instaló sin la carpeta `data/` |

---

## Licencia

Propietaria. Ver el paquete en [PyPI](https://pypi.org/project/ghl-pro-mcp/).
