# Primeros pasos con MCP

Conecta un cliente MCP a UTILIA OS: los servidores, cómo autorizar el acceso, la primera llamada y cómo invocar las herramientas desde el SDK.

UTILIA OS publica sus datos para asistentes de IA y agentes mediante el protocolo MCP (Model Context Protocol): servidores remotos que hablan JSON-RPC sobre HTTP y se autorizan con OAuth 2.1. Este artículo te lleva de cero a tu primera llamada: qué servidor elegir, cómo autorizar el acceso, cómo es el intercambio inicial y cómo invocar las herramientas desde tu propio código. La credencial es un token OAuth o una clave de conexión personal, emitidos para un servidor concreto.

Si solo quieres conectar Claude, ChatGPT o Cursor sin programar nada, la guía de uso [Conecta tu IA](https://os.utilia.ai/docs/guides/connect-ai/overview) cuenta el proceso paso a paso.

## Qué necesitas

- Una cuenta de UTILIA OS con permiso sobre lo que quieras consultar. El servidor hereda tus permisos y su alcance: nunca ve más que tú.
- Que tu organización tenga contratado el aplicativo de cada área que conectes. Si no lo tiene, el servidor lo rechaza aunque tengas el permiso.
- Un cliente MCP que admita el transporte HTTP (Claude, ChatGPT, Cursor, Claude Code u otro), o tu propio código.

## Los servidores

Cada servidor cubre un área del producto y solo anuncia las herramientas de esa área. Son las mismas direcciones que ofrece la pantalla [Conecta tu IA](https://os.utilia.ai/dashboard/settings/connect-ai), donde ves las de tu plan y, con un candado, las que tu organización podría contratar:

| Área | Servidor | Dirección | Qué cubre |
| - | - | - | - |
| CRM | `utilia-crm` | `https://os.utilia.ai/api/mcp/crm` | Clientes, contactos, leads, oportunidades, presupuestos, tareas, interacciones, proyectos de cliente, calendario, reuniones, tickets de soporte, gestor de archivos y ajustes de la organización |
| Gestión de proyectos | `utilia-work` | `https://os.utilia.ai/api/mcp/work` | Elementos de trabajo, proyectos, ciclos, base de conocimiento, horas, AI Studio y aplicaciones externas |
| Finanzas | `utilia-finance` | `https://os.utilia.ai/api/mcp/finance` | Facturas, rectificativas, suscripciones, gastos, proveedores, configuración fiscal y el resumen de Finanzas. Tesorería, impuestos, contabilidad, informes y comisiones, próximamente |
| Marketing | `utilia-marketing` | `https://os.utilia.ai/api/mcp/marketing` | Campañas, listas, plantillas, automatizaciones, supresiones, informes y entregabilidad |
| Chat | `utilia-chat` | `https://os.utilia.ai/api/mcp/chat` | Canales, mensajes y asistentes de IA de los canales. No envía mensajes |
| RRHH | `utilia-rrhh` | `https://os.utilia.ai/api/mcp/rrhh` | Fichaje de la jornada, ausencias, vacaciones y saldos |

Hay herramientas que se repiten en varios servidores con el mismo contrato: `notifications` y `org_plan` están en todos, y `search`, en CRM, Gestión de proyectos y Finanzas. Lo que cambia entre copias es lo que alcanza el token. El detalle está en [Buscador global y avisos por MCP](https://os.utilia.ai/docs/developers/mcp/search-and-notifications).

Estos servidores trabajan con los datos de una empresa. Para que tu asistente trabaje con tu **cuenta de desarrollador** (tus aplicaciones, sus fichas y tus empresas de prueba) hay un servidor aparte, `utilia-developers`, en `https://os.utilia.ai/api/mcp/developers`, que solo admite cuentas de desarrollador: lo explica [Conectar tu asistente de IA a la consola](https://os.utilia.ai/docs/developers/console/mcp).

> **Atención: La dirección antigua del servidor de trabajo se retira en diciembre de 2026**
>
> El servidor de Gestión de proyectos se llamaba `utilia-dev` y respondía en `/api/mcp/dev`. Esa dirección sigue funcionando como alias hasta diciembre de 2026, y mientras tanto su respuesta a `initialize` empieza con un aviso de migración. Cambia tu configuración a `/api/mcp/work`: un token emitido para una de las dos direcciones vale para la otra, así que no tienes que volver a autorizar.

## Autorizar el acceso

Todas las llamadas llevan la cabecera `Authorization: Bearer <token>`. Hay dos formas de conseguir ese token:

- **Autorización por navegador (OAuth 2.1 con PKCE)**. Es la forma recomendada y la que usan los asistentes cuando pegas la dirección del servidor. El cliente lo descubre todo a partir de la primera respuesta, como se ve en la figura. El detalle está en [Descubrimiento de OAuth](https://os.utilia.ai/docs/developers/oauth/discovery) y en [Scopes y recursos](https://os.utilia.ai/docs/developers/oauth/scopes-and-resources).
- **Clave de conexión personal**. Para clientes que no admiten la autorización por navegador. Se genera en Ajustes › Integraciones › Conecta tu IA, dentro del área, en «Conexión avanzada con clave (para desarrolladores)». Va atada a un solo servidor, caduca a los 90 días y admite como mucho cinco activas por servidor.

**Cómo se conecta un cliente MCP**

Participantes: Cliente MCP, Navegador y UTILIA OS.

1. Cliente MCP → UTILIA OS: `POST /api/mcp/crm`. Primera petición, todavía sin token.
2. UTILIA OS → Cliente MCP (respuesta): 401 con WWW-Authenticate. La cabecera apunta a los metadatos del recurso.
3. Cliente MCP → UTILIA OS: `GET /.well-known/oauth-protected-resource`. Averigua qué servidor de autorización usar y qué scopes admite el recurso.
4. Cliente MCP → UTILIA OS: `GET /.well-known/oauth-authorization-server`. Obtiene las direcciones de registro, autorización y token.
5. Cliente MCP → UTILIA OS: `POST /api/oauth/register`. Se registra y recibe su client_id.
6. Cliente MCP → Navegador: Abre /api/oauth/authorize. Con code_challenge (PKCE) y el servidor como resource.
7. UTILIA OS (por su cuenta): Inicias sesión y apruebas el acceso.
8. Navegador → Cliente MCP (respuesta): Vuelta con el code. A la redirect_uri del cliente.
9. Cliente MCP → UTILIA OS: `POST /api/oauth/token`. Cambia el code y el code_verifier por el token.
10. UTILIA OS → Cliente MCP (respuesta): access_token y refresh_token. El token queda atado a ese servidor.
11. Cliente MCP → UTILIA OS: `POST /api/mcp/crm · initialize`. Ya con Authorization: Bearer.
12. UTILIA OS → Cliente MCP (respuesta): serverInfo y Mcp-Session-Id. Empieza la sesión: tools/list y tools/call.

_El cliente solo necesita la dirección del servidor: el resto lo descubre a partir del primer 401._

En los dos casos el token queda atado al servidor para el que se emitió: un token del recurso `/api/mcp/crm` no sirve en `/api/mcp/finance`, y al revés tampoco.

> **Importante: La clave de conexión se muestra una sola vez**
>
> Cópiala al generarla y guárdala como una contraseña. Si la pierdes, revócala y genera otra.

## La doble puerta

Cada llamada tiene que pasar por la puerta del token y por la de tu usuario, además del plan de tu organización. Las comprobaciones van en este orden:

**Las comprobaciones de cada llamada**

1. **¿Es un token de este servidor?** (El token): Un token de /api/mcp/crm no sirve en otro servidor. Si no: error -32600, sin mirar nada más.
2. **¿Está el aplicativo en el plan?** (Tu organización): Lo decide el plan contratado; ningún permiso lo sustituye. Si no: la herramienta no aparece en tools/list y la llamada se rechaza.
3. **¿Lleva el token el scope de la operación?** (El token): No basta el scope de la herramienta: un token de solo lectura no ejecuta escrituras. Si no: la respuesta nombra el scope que falta.
4. **¿Tienes el permiso de la operación?** (Tu usuario): Aunque el token lleve el scope, sin tu permiso no hay operación. Si no: error -32602 «Permiso denegado. Requiere: ...».
5. **Se ejecuta dentro de tu alcance** (Tu usuario): El servidor recorta las filas igual que la aplicación: toda la organización, tu departamento, lo asignado o lo propio.

El scope, el permiso y la confirmación de cada operación están en la [referencia de herramientas MCP](https://os.utilia.ai/docs/developers/mcp/reference) y en la página de cada servidor.

## Tu primera llamada

Con un token válido, el intercambio es el estándar de MCP. Primero, `initialize`:

```bash
curl -s -i -X POST 'https://os.utilia.ai/api/mcp/crm' \
  -H 'Authorization: Bearer <TOKEN>' \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-11-25",
      "clientInfo": { "name": "mi-cliente", "version": "1.0.0" },
      "capabilities": {}
    }
  }'
```

La respuesta identifica el servidor (en este caso, `UTILIA CRM MCP`), incluye en `instructions` una guía de sus herramientas canónicas y devuelve en la cabecera `Mcp-Session-Id` el identificador de la sesión, que conviene reenviar en las peticiones siguientes. El servidor admite las versiones del protocolo `2025-11-25` y `2025-06-18`.

Después, `tools/list` devuelve las herramientas que tu token puede usar, y `tools/call` ejecuta una. Por ejemplo, buscar una ficha por texto:

```bash
curl -s -X POST 'https://os.utilia.ai/api/mcp/crm' \
  -H 'Authorization: Bearer <TOKEN>' \
  -H 'Content-Type: application/json' \
  -H 'Mcp-Session-Id: <SESION>' \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "search",
      "arguments": { "operation": "global", "q": "Acme" }
    }
  }'
```

Cada servidor admite hasta 60 peticiones por minuto; por encima responde con HTTP `429`.

## Llamar a las herramientas desde tu código

Los SDK oficiales envuelven algunas herramientas MCP con métodos tipados en `sdk.mcp`. Necesitas la versión actual (4.1.0) del SDK de JavaScript, con Node.js 18 o superior, o del SDK de Python, con Python 3.9 o superior.

### JavaScript / TypeScript

```bash
npm install @utilia-os/sdk-js
```

### Python

```bash
pip install utilia-sdk
```

`sdk.mcp` necesita una sesión OAuth: la clave de API que usan los servicios REST (`X-Api-Key`) no abre los servidores MCP. Configura el SDK con tu aplicación OAuth y pide la autorización indicando como `resource` el servidor al que vas a llamar:

### JavaScript / TypeScript

```typescript
import { UtiliaSDK } from '@utilia-os/sdk-js';

const sdk = new UtiliaSDK({
  baseURL: 'https://os.utilia.ai/api',
  oauth: {
    clientId: process.env.UTILIA_CLIENT_ID!,
    redirectUri: 'https://tu-app.com/callback',
    scopes: ['integrations:overview:view'],
  },
});

// 1. Envía a la persona a esta dirección para que autorice.
const authUrl = await sdk.oauth.getAuthorizationUrl({
  resource: 'https://os.utilia.ai/api/mcp/work',
});

// 2. En tu ruta de vuelta, cambia el código por el token.
await sdk.oauth.handleCallback(code);

// 3. Ya puedes llamar a las herramientas.
const status = await sdk.mcp.integrationsOverview.status();
console.log(`Aplicaciones externas: ${status.apps.total}`);
```

### Python

```python
import os
from utilia_sdk import UtiliaSDK

sdk = UtiliaSDK(
    base_url="https://os.utilia.ai/api",
    oauth={
        "client_id": os.environ["UTILIA_CLIENT_ID"],
        "redirect_uri": "https://tu-app.com/callback",
        "scopes": ["integrations:overview:view"],
    },
)

# 1. Envía a la persona a esta dirección para que autorice.
auth_url = await sdk.oauth.get_authorization_url(
    resource="https://os.utilia.ai/api/mcp/work",
)

# 2. En tu ruta de vuelta, cambia el código por el token.
await sdk.oauth.handle_callback(code)

# 3. Ya puedes llamar a las herramientas.
status = await sdk.mcp.integrations_overview.status()
print(f"Aplicaciones externas: {status.apps.total}")
```

`sdk.mcp.integrationsOverview` llama a la herramienta `integrations_overview` del servidor de Gestión de proyectos. Con el mismo patrón, `sdk.mcp.integrations` gestiona aplicaciones externas y sus webhooks, y `sdk.mcp.crm`, `sdk.mcp.marketing` y `sdk.mcp.attendance` llaman a sus servidores respectivos. Para todo lo que no tiene método tipado, invoca la herramienta por JSON-RPC como en el apartado anterior.

## Problemas frecuentes

| Síntoma | Causa más probable | Qué hacer |
| - | - | - |
| HTTP `401` en la primera petición | Falta la cabecera `Authorization`, o el token ha caducado o se ha revocado | Autoriza de nuevo o genera otra clave. El `401` trae en `WWW-Authenticate` la dirección de los metadatos del recurso |
| HTTP `401` al usar el SDK con clave de API | `sdk.mcp` no acepta `X-Api-Key` | Configura el SDK con `oauth` |
| Error `-32600` al cambiar de servidor | Cada token está atado al servidor para el que se emitió | Autoriza también el otro servidor |
| `tools/list` no muestra una herramienta | Tu token no lleva ninguno de sus scopes, o tu organización no tiene contratado su aplicativo | Pide el scope al autorizar o consulta el plan con `org_plan` |
| Error `-32602` «Permiso denegado. Requiere: ...» | Tu usuario no tiene el permiso de la operación | Pide a quien administra tu organización que te lo conceda |
| HTTP `429` | Más de 60 peticiones por minuto | Espera y reintenta solo lo pendiente |

## Siguiente paso

- [Referencia de herramientas MCP](https://os.utilia.ai/docs/developers/mcp/reference): herramientas, operaciones, scopes y permisos.
- [Poner al día una cartera de clientes](https://os.utilia.ai/docs/developers/mcp/client-portfolio): un caso completo con el servidor del CRM.
- [Avisos a tu servidor (webhooks)](https://os.utilia.ai/docs/developers/webhooks/overview): si además quieres que UTILIA OS te avise de lo que pasa, configura los webhooks de tu aplicación externa y verifica su [firma HMAC](https://os.utilia.ai/docs/developers/webhooks/hmac-signature).
