# MCP

URL canónica: https://texttree.ai/es-419/docs/mcp/
URL de Markdown: https://texttree.ai/es-419/docs/mcp.md
Tipo de página: docs
Translation status: draft
Legal status: english_controls

## Resumen

Rutas MCP actuales, alcances, envolturas de ejecución y controles de tiempo de ejecución.

## Contenido de la página

# MCP

TextTree expone una superficie MCP acotada para el descubrimiento y la ejecución controlada de herramientas.

## Rutas base

- `GET /mcp/health`
- `POST /mcp`
- `POST /mcp/accounts`
- `GET /mcp/tools`
- `POST /mcp/tools/:name`
- `GET /api/v1/mcp/oauth-clients`
- `DELETE /api/v1/mcp/oauth-clients/:client_id`
- `GET /.well-known/oauth-protected-resource/mcp`
- `GET /.well-known/oauth-authorization-server/mcp`
- `POST /oauth/register`
- `GET /oauth/authorize`
- `POST /oauth/authorize`
- `POST /oauth/token`
- `POST /oauth/revoke`

El desarrollo local con Phoenix se ejecuta en `http://localhost:4001`.

`POST /mcp` es el endpoint nativo de MCP JSON-RPC. Las rutas `/mcp/tools` son
rutas REST de compatibilidad para las integraciones existentes de TextTree y para depuración.
Actualmente TextTree opera con Streamable HTTP sin estado: los mensajes JSON-RPC se envían
con `POST /mcp`. Las sondas de flujo SSE `GET /mcp` y las solicitudes de terminación de sesión
`DELETE /mcp` devuelven `405 Method Not Allowed` porque no se asigna ninguna sesión MCP
del lado del servidor.

## Metadatos de descubrimiento

TextTree publica metadatos de descubrimiento de autorización MCP para clientes MCP HTTP:

```bash
curl https://api.texttree.ai/.well-known/oauth-protected-resource/mcp
curl https://api.texttree.ai/.well-known/oauth-authorization-server/mcp
```

Las solicitudes MCP no autenticadas devuelven `401` con un desafío `WWW-Authenticate`
que apunta a la URL de metadatos del recurso protegido. Los metadatos de autorización
anuncian compatibilidad con Client ID Metadata Document, registro dinámico de clientes,
concesiones de código de autorización, PKCE S256 e intercambio de tokens de cliente público para clientes
MCP HTTP. TextTree también sigue admitiendo el arranque de tokens bearer de primera
parte mediante `POST /mcp/accounts`. La ruta retrocompatible
`POST /api/v1/onboarding/api-key` ahora emite los tokens de acceso bearer `txt_...`
que usan MCP y la API para desarrolladores.

Flujo del cliente MCP con OAuth:

1. Prefiere un Client ID Metadata Document: establece `client_id` como una URL HTTPS que
   aloje el JSON de metadatos del cliente. Usa `POST /oauth/register` solo como
   alternativa de registro dinámico para clientes que no pueden alojar metadatos.
2. Envía al usuario a `GET /oauth/authorize` con `response_type=code`,
   `client_id`, `redirect_uri`, `resource=https://api.texttree.ai/mcp`,
   `code_challenge` y `code_challenge_method=S256`.
3. TextTree muestra una pantalla de consentimiento en el navegador con el cliente MCP, el URI de redirección,
   el recurso y los alcances solicitados. La aprobación envía `POST /oauth/authorize` y
   redirige de vuelta con `code`; el rechazo redirige de vuelta con `error=access_denied`.
4. Intercambia el código devuelto en `POST /oauth/token` con el
   `code_verifier` correspondiente y el mismo valor de `resource`. Se aceptan solicitudes JSON y
   `application/x-www-form-urlencoded`.
5. Usa el token bearer de TextTree devuelto en `POST /mcp`.
6. Revoca un token bearer en tu poder con `POST /oauth/revoke` cuando el cliente MCP
   se desconecte o rote sus credenciales.

Ejemplo de Client ID Metadata Document:

```json
{
  "client_id": "https://agent.example.com/.well-known/oauth-client.json",
  "client_name": "Example Agent",
  "client_uri": "https://agent.example.com",
  "redirect_uris": ["http://localhost:8787/callback"],
  "grant_types": ["authorization_code"],
  "response_types": ["code"],
  "scope": "mcp:read mcp:execute onboarding:read",
  "token_endpoint_auth_method": "none"
}
```

Cuando TextTree ve un `client_id` con formato de URL durante la autorización, obtiene
y valida ese documento antes de mostrar el consentimiento. La URL del documento debe usar
HTTPS en el puerto predeterminado, no debe incluir credenciales ni un fragmento, y debe
resolverse únicamente a direcciones IP públicas. Los hosts localhost, privados, de enlace local, multidifusión
y sin resolver se rechazan antes de la obtención. El JSON obtenido debe contener un
`client_id` que coincida exactamente con la URL, un `client_name`, al menos un
alcance admitido y el `redirect_uri` solicitado. Si `grant_types` o
`response_types` están presentes, deben incluir `authorization_code` y `code`.
TextTree almacena en caché los metadatos válidos según `Cache-Control: max-age` o
`Expires`; `no-cache` y `no-store` fuerzan la revalidación en la siguiente
solicitud de autorización. Los documentos sin encabezados de caché usan una ventana de caché
predeterminada corta, y TextTree limita la vida útil de la caché de metadatos a un día.

Los tokens bearer de TextTree pueden vincularse por audiencia al recurso MCP. Los nuevos tokens MCP
emitidos por el operador deben usar la URL canónica del recurso MCP como
audiencia, por ejemplo `https://api.texttree.ai/mcp`. Los tokens sin audiencia siguen
siendo aceptados por compatibilidad, pero un token vinculado por audiencia se rechaza cuando se usa
contra un recurso de TextTree distinto.

El valor OAuth `resource` está restringido a la URL del recurso MCP. Los alcances
solicitados no admitidos fallan con `invalid_scope` en lugar de ampliarse
o reducirse silenciosamente.

Los clientes OAuth MCP autorizados pueden listarse y revocarse a través de la API:

```bash
curl https://api.texttree.ai/oauth/revoke \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "token=$TEXTREE_ACCESS_TOKEN&token_type_hint=access_token"

curl https://api.texttree.ai/api/v1/mcp/oauth-clients \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN"

curl -X DELETE https://api.texttree.ai/api/v1/mcp/oauth-clients/mcp_client_... \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN"
```

`POST /oauth/revoke` sigue la convención de revocación de OAuth y devuelve `200`
para tokens desconocidos, de modo que los llamadores no filtren la existencia de tokens.
Listar requiere `mcp:read`. La revocación requiere `mcp:execute` y revoca
los tokens bearer activos de TextTree emitidos a través de ese cliente OAuth MCP para el
usuario actual.

`POST /oauth/register` y `POST /oauth/token` tienen límites de tasa por IP del cliente.
Las solicitudes limitadas por tasa devuelven `429` con un encabezado `Retry-After` y
`oauth_client_registration_rate_limited` u `oauth_token_exchange_rate_limited`.
Los cubos son independientes para que los picos de registro no agoten el intercambio de tokens
de código de autorización.

## Autenticación y alcances

Las solicitudes MCP autenticadas usan tokens bearer emitidos por TextTree. Los humanos, los usuarios
de billetera y los agentes de IA presentan el mismo encabezado `Authorization: Bearer <token>`
después de autenticarse a través de TextTree.

Los agentes de IA pueden arrancar su propia identidad de TextTree mediante `POST /mcp/accounts`
con un nombre de usuario y una contraseña. Esa ruta no requiere autenticación, devuelve códigos
de respaldo más un token bearer de TextTree, y está limitada a una creación de cuenta exitosa
por dirección IP cada cinco minutos.

Los alcances actuales a nivel de ruta son:

- `POST /mcp` acepta `initialize` y `ping` con cualquier token autenticado
- `POST /mcp` `tools/list`, `resources/list`, `resources/templates/list`, `prompts/list` y `completion/complete` requieren `mcp:read`
- `POST /mcp` `resources/read` requiere el alcance específico del recurso
- `POST /mcp` `tools/call` requiere `mcp:execute`
- `GET /mcp/tools` requiere `mcp:read`
- `POST /mcp/tools/:name` requiere `mcp:execute`
- `GET /api/v1/mcp/oauth-clients` requiere `mcp:read`
- `DELETE /api/v1/mcp/oauth-clients/:client_id` requiere `mcp:execute`

Las entradas de herramientas también pueden declarar un alcance requerido más específico en el registro del servidor. Si eso
ocurre, TextTree registra una auditoría de ejecución bloqueada y devuelve `403 insufficient_scope`.

## MCP JSON-RPC nativo

`POST /mcp`

TextTree admite JSON-RPC estilo MCP sobre HTTP para clientes que esperan los métodos
MCP estándar. El endpoint requiere un token bearer de TextTree y devuelve el
encabezado de respuesta `mcp-protocol-version`.
Las envolturas de solicitud JSON-RPC deben incluir `jsonrpc: "2.0"`. Los ID de solicitud deben ser
cadenas o enteros; los ID `null` explícitos se rechazan, y las formas de ID no válidas no se
repiten en las respuestas de error. Los nombres de métodos deben ser cadenas. Las envolturas de solicitud
son estrictas: solo se aceptan `jsonrpc`, `id`, `method`, `params` y el campo
de nivel superior reservado por MCP `_meta`. Todo campo `_meta` debe ser un objeto JSON.
Cuando los params de la solicitud incluyen `_meta.progressToken`, el token debe ser una cadena o
un entero. Actualmente TextTree trata los tokens de progreso como metadatos consultivos y no
emite notificaciones de progreso.

Versiones de protocolo admitidas:

- `2025-11-25`
- `2025-06-18`
- `2025-03-26`

Durante `initialize`, TextTree negocia el `params.protocolVersion` solicitado
cuando es compatible. Si una solicitud de initialize pide una versión de cadena no admitida,
TextTree responde con su versión compatible más reciente en lugar de fallar
el handshake. Para las solicitudes posteriores, los clientes deben enviar el
encabezado `MCP-Protocol-Version` con la versión negociada. Si no hay encabezado
presente, TextTree recurre a `2025-03-26` por compatibilidad. Los encabezados de versión
de protocolo no admitidos devuelven `400 Bad Request`, conforme al requisito del transporte
MCP Streamable HTTP.
Si se proporciona, `initialize.params.protocolVersion` debe ser una cadena,
`capabilities` debe ser un objeto, y `clientInfo` debe ser un objeto con un
`name` de tipo cadena y una `version` de tipo cadena opcional. Los params de initialize desconocidos se
rechazan, excepto el campo `_meta` reservado por MCP.
`ping` acepta un objeto de params vacío o `_meta`; otros params de ping se rechazan.

`POST /mcp` requiere un encabezado `Accept` que incluya tanto `application/json`
como `text/event-stream`, más `Content-Type: application/json`. Las sondas de flujo
`GET /mcp` requieren `text/event-stream`. Las solicitudes que omiten los tipos de respuesta
anunciados devuelven `406 Not Acceptable`; las solicitudes POST con un tipo de contenido
distinto de JSON devuelven `415 Unsupported Media Type`.

Las solicitudes de transporte MCP originadas en el navegador también deben pasar la validación de Origin.
Las solicitudes sin encabezado `Origin` se aceptan para clientes MCP del lado del servidor y de CLI.
Cuando hay un encabezado `Origin` presente, debe coincidir con el origen de la solicitud,
el origen configurado de la app pública o del sitio de TextTree, o un origen de desarrollo
local de loopback. Los orígenes de navegador no confiables devuelven `403 forbidden_origin`.

### Initialize

```bash
curl https://api.texttree.ai/mcp \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "init-1",
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-11-25",
      "capabilities": {},
      "clientInfo": {
        "name": "agent-client",
        "version": "0.1.0"
      }
    }
  }'
```

El éxito devuelve las capacidades y la identidad del servidor:

```json
{
  "jsonrpc": "2.0",
  "id": "init-1",
  "result": {
    "protocolVersion": "2025-11-25",
    "capabilities": {
      "prompts": {
        "listChanged": false
      },
      "completions": {},
      "resources": {
        "listChanged": false
      },
      "tools": {
        "listChanged": false
      }
    },
    "serverInfo": {
      "name": "texttree",
      "version": "0.1.0"
    },
    "instructions": "TextTree exposes audited SMS onboarding and messaging workflows..."
  }
}
```

Los clientes pueden colocar las `instructions` devueltas en el contexto del modelo. Las
instrucciones resumen las reglas de flujo de trabajo específicas de TextTree: preferir Dedicated
Number para una identidad de remitente estable, leer los recursos antes de ejecutar herramientas, usar
`messages.send` solo con SMS aprobados por el destinatario y una `idempotency_key`
estable, y confiar en las compuertas de supresión, gasto, preparación del remitente
y trabajador de entrega de TextTree para los envíos de producción.

### Listar herramientas MCP

```bash
curl https://api.texttree.ai/mcp \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "tools-1",
    "method": "tools/list",
    "params": {}
  }'
```

`tools/list` requiere `mcp:read`. Cada herramienta incluye un título, un `inputSchema` de JSON Schema
2020-12, un `outputSchema` de JSON Schema 2020-12, anotaciones de seguridad de MCP
y metadatos de TextTree para el alcance requerido y el tiempo de espera.
`tools/list` admite paginación por cursor de MCP. Trata `nextCursor` como opaco y
devuélvelo como `params.cursor` solo en la siguiente solicitud de `tools/list`. Las solicitudes
de listado aceptan solo `cursor` y el campo `_meta` reservado por MCP.

### Listar recursos MCP

```bash
curl https://api.texttree.ai/mcp \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "resources-1",
    "method": "resources/list",
    "params": {}
  }'
```

`resources/list` requiere `mcp:read`. Los recursos exponen contexto de solo lectura con
metadatos de alcance para que los agentes puedan inspeccionar el estado sin ejecutar una herramienta.
`resources/list` admite paginación por cursor de MCP. Trata `nextCursor` como opaco
y devuélvelo como `params.cursor` solo en la siguiente solicitud de `resources/list`.
Las solicitudes de listado aceptan solo `cursor` y el campo `_meta` reservado por MCP.

Recursos actuales:

- `texttree://mcp/tools` requiere `mcp:read`
- `texttree://onboarding/status` requiere `onboarding:read`
- `texttree://billing/status` requiere `onboarding:read`
- `texttree://messages/recent` requiere `messages:write`

### Listar plantillas de recursos MCP

```bash
curl https://api.texttree.ai/mcp \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "resource-templates-1",
    "method": "resources/templates/list",
    "params": {}
  }'
```

`resources/templates/list` requiere `mcp:read` y devuelve plantillas de recursos
seguras por ID para el sondeo de agentes:

- `texttree://invoices/{id}` requiere `onboarding:read`
- `texttree://messages/{id}` requiere `messages:write`
- `texttree://numbers/{id}` requiere `numbers:read`
- `texttree://onboarding/checklist` requiere `onboarding:read`
- `texttree://billing/readiness` requiere `onboarding:read`
- `texttree://elicitations/{correlation_id}` requiere `onboarding:read`

Admite el mismo contrato de paginación por cursor que los demás métodos de listado, y
acepta solo `cursor` más el campo `_meta` reservado por MCP.

### Leer un recurso MCP

```bash
curl https://api.texttree.ai/mcp \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "resource-read-1",
    "method": "resources/read",
    "params": {
      "uri": "texttree://onboarding/status"
    }
  }'
```

`resources/read` devuelve contenido JSON en el arreglo `contents` de MCP. Las lecturas
de recursos aplican el alcance de TextTree específico del recurso antes de devolver datos.
`texttree://messages/recent` y `texttree://messages/{id}` omiten los números de teléfono
y los cuerpos de los mensajes; úsalos para contexto de estado de entrega, no para contenido privado
del destinatario. `texttree://numbers/{id}` oculta el número de teléfono completo y devuelve
estado, uso, capacidades y estado de cumplimiento. Todas las lecturas por ID están limitadas al
usuario o espacio de trabajo actual de TextTree. `texttree://elicitations/{correlation_id}`
devuelve el estado reanudable de un traspaso en modo URL de financiamiento, consentimiento o configuración
de número.

### Listar prompts MCP

```bash
curl https://api.texttree.ai/mcp \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "prompts-1",
    "method": "prompts/list",
    "params": {}
  }'
```

`prompts/list` requiere `mcp:read`. Los prompts empaquetan flujos de trabajo comunes de TextTree
en instrucciones reutilizables para agentes.
`prompts/list` admite paginación por cursor de MCP. Trata `nextCursor` como opaco y
devuélvelo como `params.cursor` solo en la siguiente solicitud de `prompts/list`. Las solicitudes
de listado aceptan solo `cursor` y el campo `_meta` reservado por MCP.

Prompts actuales:

- `texttree.onboard_agent` acepta opcionalmente `path` (`dedicated_number` o
  `fast_send`), `region`, `brand_name`, `website`, `funding_amount_cents`,
  `payment_method`, `recipient_phone_number`, `secret_storage` y
  `execution_policy`
- `texttree.first_send` acepta opcionalmente `sender_path` (`dedicated_number` o
  `fast_send`) y una cadena opcional `recipient_context`

Los argumentos de los prompts son estrictos. Los nombres de argumentos desconocidos, los tipos incorrectos y los valores
de enum de sender-path no válidos devuelven `-32602 Invalid params`.

### Obtener un prompt MCP

```bash
curl https://api.texttree.ai/mcp \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "prompt-1",
    "method": "prompts/get",
    "params": {
      "name": "texttree.onboard_agent",
      "arguments": {
        "path": "dedicated_number",
        "region": "US"
      }
    }
  }'
```

Las respuestas de prompts devuelven `messages` de MCP que un cliente puede colocar en el contexto
del modelo antes de llamar a recursos o herramientas.

### Completar argumentos de prompts MCP

```bash
curl https://api.texttree.ai/mcp \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "complete-1",
    "method": "completion/complete",
    "params": {
      "ref": {
        "type": "ref/prompt",
        "name": "texttree.onboard_agent"
      },
      "argument": {
        "name": "path",
        "value": "d"
      }
    }
  }'
```

`completion/complete` requiere `mcp:read` y devuelve sugerencias no sensibles
para los argumentos de prompts de TextTree. Las completaciones actuales cubren `path`,
`sender_path` y `region`. Los argumentos de formato libre devuelven una lista de completación
vacía. TextTree no expone plantillas de recursos, por lo que las solicitudes de completación
de plantillas de recursos devuelven `-32602 Invalid params`.

### Llamar a una herramienta MCP

```bash
curl https://api.texttree.ai/mcp \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "call-1",
    "method": "tools/call",
    "params": {
      "name": "onboarding.status",
      "arguments": {}
    }
  }'
```

`tools/call` requiere `mcp:execute` más el alcance específico de la herramienta declarado en
el registro. Los resultados incluyen `content` de MCP, `structuredContent`, `isError`,
`_meta` de MCP y la envoltura de auditoría de ejecución de TextTree. La carga
`structuredContent` coincide con el `outputSchema` anunciado de cada herramienta.
El `_meta` del resultado de la llamada a la herramienta contiene campos de correlación seguros:
`texttree/execution_id`, `texttree/tool`, `texttree/outcome` y
`texttree/is_error`. Los mismos metadatos se incluyen bajo
`structuredContent._meta` para que el `outputSchema` anunciado coincida con la carga
de resultado legible por máquina. No incluye números de teléfono ni cuerpos de
mensajes.

TextTree valida los argumentos de herramientas conocidos contra el `inputSchema` anunciado
de cada herramienta antes de la ejecución. Los campos requeridos faltantes, los campos desconocidos, los tipos
incorrectos, los valores de enum no válidos y las violaciones de mínimos devuelven `-32602 Invalid
params` sin ejecutar la herramienta.
Los params de los métodos JSON-RPC también son estrictos: `prompts/get`, `resources/read` y
`tools/call` rechazan los params de nivel superior desconocidos, aceptando el campo `_meta`
reservado por MCP. El `_meta` de la llamada a la herramienta se pasa al contexto del ejecutor como
metadatos MCP de canal lateral y no se fusiona con los `arguments` de la herramienta.
Si `_meta.progressToken` está presente, debe ser una cadena o un entero.
El `arguments.metadata` de las herramientas de mensajes es un metadato separado propiedad del llamador y puede
contener campos de objeto JSON arbitrarios para correlación.

`messages.send` es una herramienta MCP real. Se encola por la misma ruta de mensajería
de TextTree que `POST /api/v1/messages`, incluidas las compuertas de supresión, gasto y
trabajador de entrega. Sus anotaciones MCP la marcan como destructiva y
de mundo abierto porque puede encolar un SMS saliente y consumir saldo de la cuenta.

Los errores JSON-RPC usan envolturas de respuesta estándar al estilo MCP y preservan
los detalles de seguridad de TextTree en `error.data`, incluidos `required_scope`,
`quota_exceeded`, `tool_not_allowed`, el tiempo de espera y los datos de auditoría de ejecución cuando
están disponibles.

### Lotes y notificaciones

Los lotes JSON-RPC se aceptan solo cuando la versión efectiva del protocolo es la
versión de compatibilidad `2025-03-26`. Las revisiones posteriores de MCP eliminaron los mensajes por lotes
del esquema del protocolo, por lo que los clientes que negocian `2025-06-18` o
`2025-11-25` deben enviar un mensaje JSON-RPC por cada `POST /mcp`; los arreglos de lotes en
esas versiones devuelven `-32600 Invalid Request` con `error.data.error` establecido en
`batch_not_supported`.

Para los lotes de compatibilidad `2025-03-26`, TextTree devuelve un objeto de respuesta por
solicitud y omite las respuestas para notificaciones y mensajes de respuesta JSON-RPC.
Los lotes de solo notificaciones y de solo respuestas devuelven `202` con un cuerpo vacío.
Actualmente TextTree no inicia solicitudes de servidor a cliente, por lo que los mensajes de
respuesta del cliente se aceptan como entradas de transporte sin efecto cuando incluyen un
`id` válido de cadena o entero. Los mensajes de respuesta de resultado deben incluir un `result`
de tipo objeto; los mensajes de respuesta de error deben incluir un `error` de tipo objeto con un `code`
entero y un `message` de tipo cadena. Envía `initialize` como una solicitud independiente; si
aparece dentro de un lote, TextTree devuelve `-32600 Invalid Request` para ese elemento
del lote. Los lotes de compatibilidad tienen un límite de 100 elementos; los lotes más grandes devuelven una
única respuesta `-32600 Invalid Request` con `error.data.error` establecido en
`batch_too_large`.
Los métodos del espacio de nombres `notifications/` se tratan como notificaciones de tipo
disparar y olvidar, y nunca reciben respuestas JSON-RPC. Actualmente TextTree actúa sobre
`notifications/initialized` y acepta las notificaciones de cancelación como consultivas;
los nombres de notificación desconocidos se ignoran. Los métodos de solicitud ordinarios como
`ping`, `tools/list` y `tools/call` deben incluir un `id`.

```bash
curl https://api.texttree.ai/mcp \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "jsonrpc": "2.0",
      "id": "ping-1",
      "method": "ping",
      "params": {}
    },
    {
      "jsonrpc": "2.0",
      "method": "notifications/initialized",
      "params": {}
    },
    {
      "jsonrpc": "2.0",
      "id": "tools-1",
      "method": "tools/list",
      "params": {}
    }
  ]'
```

### Prueba de humo de compatibilidad

Para un servidor Phoenix en ejecución, TextTree incluye una tarea de prueba de humo de compatibilidad que
recorre el endpoint MCP nativo a través de initialize, la notificación initialized,
las herramientas, los recursos, los prompts y una llamada a la herramienta de estado de onboarding.

```bash
cd apps/web
TEXTREE_ACCESS_TOKEN=txt_... mix textree.mcp.smoke --url http://localhost:4001/mcp
mix textree.mcp.smoke --url http://localhost:4001/mcp --bootstrap-local-token
```

El token debe incluir `mcp:read`, `mcp:execute` y `onboarding:read`.
Pasa `--skip-execute` para omitir la llamada a la herramienta de estado de onboarding al validar
un token de solo lectura. `--bootstrap-local-token` crea un token de una hora en la
base de datos local actual y se rechaza para URLs de MCP que no sean localhost.

Para los tokens bearer emitidos por el operador, vincula el token al recurso MCP:

```bash
mix textree.auth.issue_token agent@example.com \
  --scopes mcp:read,mcp:execute,onboarding:read,messages:write \
  --audience https://api.texttree.ai/mcp
```

## Listar herramientas

`GET /mcp/tools`

```bash
curl https://api.texttree.ai/mcp/tools \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN"
```

El éxito devuelve una lista de herramientas respaldada por el registro:

```json
{
  "tools": [
    {
      "name": "messages.send",
      "description": "Trigger a message send through the MCP surface.",
      "required_scope": "messages:write",
      "timeout_ms": 1000
    },
    {
      "name": "onboarding.status",
      "description": "Inspect token, balance, invoice, and SMS onboarding state.",
      "required_scope": "onboarding:read",
      "timeout_ms": 1000
    },
    {
      "name": "onboarding.create_invoice",
      "description": "Create or reuse a launch funding invoice.",
      "required_scope": "onboarding:write",
      "timeout_ms": 1000
    },
    {
      "name": "onboarding.invoice_status",
      "description": "Check funding invoice status for programmatic onboarding.",
      "required_scope": "onboarding:read",
      "timeout_ms": 1000
    },
    {
      "name": "onboarding.test_sms",
      "description": "Send the fixed Fast Send onboarding test SMS.",
      "required_scope": "onboarding:write",
      "timeout_ms": 1000
    },
    {
      "name": "onboarding.request_dedicated_number",
      "description": "Submit business details for the recommended Dedicated Number path.",
      "required_scope": "onboarding:write",
      "timeout_ms": 1000
    }
  ]
}
```

El registro alfa actual se configura del lado del servidor. No existe una superficie de administración pública para mutar
el registro en tiempo de ejecución.

## Crear una cuenta sin interfaz

`POST /mcp/accounts`

Usa esta ruta cuando un cliente de IA necesita una cuenta y un token bearer sin
correo electrónico, OAuth de Google ni autenticación de billetera.

```bash
curl https://api.texttree.ai/mcp/accounts \
  -H "Content-Type: application/json" \
  -d '{
    "account": {
      "username": "agent-demo",
      "password": "correct horse battery staple"
    }
  }'
```

El éxito devuelve el nombre de usuario público, códigos de respaldo de un solo uso y un token bearer:

```json
{
  "account": {
    "id": "9d7d9df7-58a0-4716-b82e-7ad5e73f7b36",
    "username": "agent-demo"
  },
  "backup_codes": ["AAAA-BBBB-CCCC-DDDD"],
  "token": {
    "type": "Bearer",
    "access_token": "txt_...",
    "scopes": [
      "messages:write",
      "mcp:read",
      "mcp:execute",
      "campaigns:read",
      "campaigns:write",
      "numbers:read",
      "numbers:write",
      "onboarding:read",
      "onboarding:write"
    ],
    "expires_at": "2026-06-03T15:30:00Z"
  }
}
```

Guarda el token y los códigos de respaldo de inmediato. TextTree no devuelve el
correo electrónico sintético interno, el hash del token, la IP sin procesar ni el hash de IP. Las fallas de validación
devuelven `422 validation_failed`; la creación exitosa y repetida de cuentas desde la
misma IP en un lapso de cinco minutos devuelve `429 account_creation_rate_limited`.

Los tokens de cuentas sin interfaz incluyen un valor `expires_at`. Las integraciones de agentes
duraderas deben usar un token emitido por el operador con una vida útil y una audiencia
intencionales, o incluir un plan de reemisión y rotación de tokens. No
almacenes tokens bearer sin procesar ni códigos de respaldo en registros, en el historial del shell ni en archivos
confirmados en el repositorio.

## Prompt seguro de onboarding MCP

Usa un prompt con objetivos del mundo real explícitos y límites de aprobación antes de que un
agente comience la configuración:

```txt
Set up TextTree.ai SMS for my AI agent using https://texttree.ai/docs/mcp/.
Auto-generate account credentials; register the dedicated number under brand
"AlphaGrowth" / https://alphagrowth.io/ (US). Store the token and backup codes
in a gitignored .env. Create a $100 USDC funding invoice and give me the
deposit details to pay; do not attempt payment yourself. Once funded, send a
test SMS to +1XXXXXXXXXX and show me how to poll for inbound replies; I will
text the number myself to test inbound. Then save the assigned number, API base
URL, token location, and MCP connect steps to a README, and write live and
mocked bash/curl test scripts for send and receive. Pause for my OK before
anything that spends money, provisions or changes a number, or sends an SMS.
```

Si falta alguno de los siguientes elementos: número de teléfono, marca, sitio web, método de financiamiento,
destino de almacenamiento de secretos o límite de aprobación, recopílalo antes de ejecutar herramientas.
Los agentes no deben inventar números de destinatarios, realizar pagos ni simular SMS
entrantes que requieren un teléfono propiedad de un humano.

## Runbook de onboarding MCP

Pasos ejecutables por el agente:

1. Crea o elige un token bearer y almacénalo en el destino de secretos solicitado.
2. Lee `texttree://onboarding/status` y `texttree://billing/status`.
3. Tras la aprobación explícita, llama a `onboarding.request_dedicated_number` solo
   cuando el nombre de la marca, el sitio web HTTPS y la región sean explícitos.
4. Tras la aprobación explícita, llama a `onboarding.create_invoice` con un monto
   explícito y un método admitido, y luego entrega al humano los detalles de pago
   devueltos.
5. Sondea `onboarding.invoice_status` o `texttree://invoices/{id}` hasta que el estado
   del pago cambie.
6. Tras la aprobación, llama a `onboarding.test_sms` o `messages.send` con el
   número de teléfono explícito del destinatario y una `idempotency_key` estable.
7. Sondea `/api/v1/messages/$MESSAGE_ID` o `texttree://messages/{id}` para conocer
   el estado de entrega.

Pasos de pago a cargo del humano:

1. Revisa el monto de la factura, la cadena, el token, la billetera y el vencimiento.
2. Paga la factura fuera del agente.
3. Indica al agente que reanude el sondeo después de que el pago haya sido enviado.

Pasos de prueba de entrada a cargo del humano:

1. Espera hasta que el número asignado esté conectado.
2. Envía un mensaje de texto al número asignado desde un teléfono real.
3. Pide al agente los comandos de sondeo de recepción o los pasos de inspección de webhooks.

Pasos que requieren aprobación explícita:

- Crear un traspaso de financiamiento o una factura destinada a un pago real.
- Solicitar, aprovisionar o cambiar un número dedicado.
- Enviar cualquier SMS a un número de teléfono real.
- Almacenar o rotar tokens bearer y códigos de respaldo.

## Ejecutar una herramienta

`POST /mcp/tools/:name`

### Cuerpo de la solicitud

```json
{
  "params": {}
}
```

### curl

```bash
curl https://api.texttree.ai/mcp/tools/onboarding.status \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"params": {}}'
```

### JavaScript

```js
const response = await fetch("https://api.texttree.ai/mcp/tools/onboarding.status", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.TEXTREE_ACCESS_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ params: {} }),
});

const { execution } = await response.json();
```

### Respuesta exitosa

```json
{
  "execution": {
    "id": "513f6a41-2c33-4c15-b4e2-10da14ab806f",
    "tool": "onboarding.status",
    "outcome": "succeeded",
    "params_summary": {},
    "result_summary": {
      "complete": false,
      "product_mode": "instant_send"
    },
    "error_message": null,
    "duration_ms": 3,
    "inserted_at": "2026-04-26T21:02:15Z"
  }
}
```

## Respuestas de error

- `403` con `{"error":"tool_not_allowed"}` cuando la herramienta está fuera de la lista de permitidos configurada
- `403` con `{"error":"insufficient_scope","required_scope":"..."}` cuando el token carece del
  alcance a nivel de ruta o a nivel de herramienta
- `429` con `{"error":"quota_exceeded"}` cuando la ventana de cuota por identidad está agotada
- `504` con `{"error":"execution_timed_out"}` cuando la ejecución excede el tiempo de espera configurado
- `422` con `{"error":"execution_failed"}` cuando el ejecutor devuelve un error

Todas estas rutas de ejecución devuelven una envoltura `execution` cuando TextTree pudo crear un
registro de auditoría.

Las respuestas MCP `403 insufficient_scope` también incluyen un desafío `WWW-Authenticate`
con `error="insufficient_scope"`, el `scope` requerido y la
URL de metadatos del recurso protegido. Los clientes MCP pueden usar ese encabezado para activar un
flujo de autorización escalonada y solicitar el alcance faltante sin adivinar.

## Controles de tiempo de ejecución

El tiempo de ejecución MCP alfa actual es intencionalmente estricto:

- la ejecución está condicionada por los alcances de los tokens bearer de TextTree
- las herramientas deben existir en el registro del servidor
- las herramientas también deben estar presentes en el límite de la lista de permitidos
- las ejecuciones se persisten con actor, identidad del token, herramienta, resumen de params, resultado y marca de tiempo
- las cuotas por identidad se aplican sobre una ventana móvil
- los tiempos de espera por herramienta o globales detienen el trabajo de larga duración
- el registro de clientes OAuth y el intercambio de tokens tienen límites de tasa por IP independientes

Valores predeterminados de límite de tasa de OAuth y variables de entorno de producción:

- registro de clientes: 20 solicitudes por IP, recarga cada 60 segundos con
  `TEXTREE_OAUTH_CLIENT_REGISTRATION_RATE_LIMIT_CAPACITY` y
  `TEXTREE_OAUTH_CLIENT_REGISTRATION_RATE_LIMIT_REFILL_MS`
- intercambio de tokens: 60 solicitudes por IP, recarga cada 60 segundos con
  `TEXTREE_OAUTH_TOKEN_EXCHANGE_RATE_LIMIT_CAPACITY` y
  `TEXTREE_OAUTH_TOKEN_EXCHANGE_RATE_LIMIT_REFILL_MS`

## Patrón de onboarding programático

Usa la API de onboarding y las herramientas MCP para completar la configuración sin adivinar cuál
es el siguiente paso. Dedicated Number es la ruta recomendada cuando un agente necesita un
remitente persistente que las personas puedan guardar y al que puedan responder. Fast Send está disponible
cuando el objetivo es la primera prueba de envío saliente más rápida a través de remitentes
instantáneos agrupados.

### 1. Crea o elige un token

Crea una cuenta sin interfaz mediante `POST /mcp/accounts`, o crea un token bearer
de TextTree en la app autenticada con los alcances necesarios para tu ruta:

- `onboarding:read` para inspeccionar el estado del onboarding y las facturas
- `onboarding:write` para crear facturas, envíos de prueba y solicitudes de número dedicado
- `messages:write` para enviar el primer SMS de producción a través de `/api/v1/messages`
- `mcp:read` y `mcp:execute` para listar y ejecutar herramientas MCP

No uses una clave API heredada `txk_...` para este flujo. `POST
/api/v1/onboarding/api-key` devuelve un token bearer `txt_...` para los llamadores que
ya tienen un token con alcance de onboarding.

Los tokens bearer emitidos por el operador deben crearse con los alcances exactos que necesita
el cliente. Para el onboarding MCP más el primer envío, usa:

```bash
cd apps/web && mix textree.auth.issue_token agent@example.com \
  --scopes onboarding:read,onboarding:write,mcp:read,mcp:execute,messages:write \
  --audience https://api.texttree.ai/mcp
```

Guarda los tokens devueltos de inmediato. Los tokens sin procesar se muestran una sola vez.

### 2. Verifica el estado del onboarding

Usa la API o la herramienta MCP para inspeccionar el progreso del token, el saldo, la factura, el número y
el primer SMS.

```bash
curl https://api.texttree.ai/api/v1/onboarding \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN"
```

```bash
curl https://api.texttree.ai/mcp/tools/onboarding.status \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"params": {}}'
```

### 3. Elige una ruta de número

Recomendado: Dedicated Number. Úsalo cuando el agente necesita un remitente estable,
respuestas entrantes, reconocimiento por parte de los clientes o un número que los operadores puedan gestionar. La
herramienta MCP nativa guarda los detalles del negocio y devuelve metadatos de elicitación en modo URL
que apuntan al flujo de configuración alojado de TextTree.

```bash
curl https://api.texttree.ai/mcp \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "dedicated-number-1",
    "method": "tools/call",
    "params": {
      "name": "onboarding.request_dedicated_number",
      "arguments": {
        "brand_name": "Acme Support",
        "website": "https://acme.example",
        "region": "US"
      }
    }
  }'
```

Fast Send. Úsalo para la primera prueba de envío saliente más rápida cuando aún no se necesita un
número dedicado. La herramienta MCP nativa envía el texto de prueba de onboarding fijo
a través de la misma ruta de prueba de Fast Send que la API.

```bash
curl https://api.texttree.ai/mcp \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "test-sms-1",
    "method": "tools/call",
    "params": {
      "name": "onboarding.test_sms",
      "arguments": {
        "phone_number": "+15551234567"
      }
    }
  }'
```

`test-sms` usa un texto de onboarding fijo, puede ejecutarse antes del financiamiento cuando la cuenta
tiene una asignación disponible de Fast Send Sandbox, y tiene límite de tasa. Una solicitud
repetida puede devolver `429 test_sms_rate_limited` con `next_allowed_at`; después de que se
use el SMS de sandbox incluido, continúa agregando saldo.

### 4. Financia el espacio de trabajo

Crea o reutiliza una factura de financiamiento de lanzamiento con un monto que satisfaga el
mínimo de onboarding actual. Prefiere la herramienta MCP de facturas durante el onboarding
de agentes. El resultado incluye metadatos de elicitación en modo URL con una URL de acción
alojada de TextTree para completar el pago.

```bash
curl https://api.texttree.ai/mcp/tools/onboarding.create_invoice \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "params": {
      "amount_cents": 10000,
      "payment_method": "direct_usdc"
    }
  }'
```

Sondea la factura hasta que pase a `paid`, `underpaid`, `expired` o
`review_required`.

```bash
curl https://api.texttree.ai/api/v1/onboarding/funding-invoices/$INVOICE_ID \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN"
```

```bash
curl https://api.texttree.ai/mcp/tools/onboarding.invoice_status \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "params": {
      "id": "'"$INVOICE_ID"'"
    }
  }'
```

Para `onboarding.invoice_status`, proporciona exactamente uno de `id` o `invoice_id`.
La plantilla de recurso por ID también puede usarse para el sondeo:

```bash
curl https://api.texttree.ai/mcp \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "invoice-resource-1",
    "method": "resources/read",
    "params": {
      "uri": "texttree://invoices/'"$INVOICE_ID"'"
    }
  }'
```

Las cargas de elicitación en modo URL incluyen `mode: "url"`, un `kind`, un
`correlation_id`, un `status_uri`, una `url` alojada, un `prompt` legible por humanos,
`expires_at` y `status: "pending"`. Trata la URL como un traspaso de acción al usuario;
no trates la salida del modelo por sí sola como aprobación de financiamiento, consentimiento o
aprovisionamiento de número. Los agentes pueden reanudar sondeando `status_uri`:

```bash
curl https://api.texttree.ai/mcp \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "elicitation-resource-1",
    "method": "resources/read",
    "params": {
      "uri": "texttree://elicitations/'"$CORRELATION_ID"'"
    }
  }'
```

El recurso de elicitación está limitado al usuario actual de TextTree. Los ID de correlación
desconocidos o de otro usuario devuelven `resource_not_found`; los traspasos pendientes pasan
a `expired` después de su marca de tiempo `expires_at`.

### 5. Envía el primer SMS de producción

Después de que el espacio de trabajo esté financiado y, para la ruta recomendada, el número
dedicado esté conectado, envía mediante `tools/call` con `messages.send` o
el endpoint normal de mensajes V1. Ambas rutas usan las mismas compuertas de supresión, gasto,
idempotencia, preparación del remitente y trabajador de entrega.

Llamada a la herramienta MCP:

```bash
curl https://api.texttree.ai/mcp \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "send-1",
    "method": "tools/call",
    "params": {
      "name": "messages.send",
      "arguments": {
        "phone_number": "+15551234567",
        "body": "Thanks for connecting with Acme Support. Reply here any time.",
        "idempotency_key": "first-send-2026-06-07"
      }
    }
  }'
```

Ruta de compatibilidad de la API V1:

```bash
curl https://api.texttree.ai/api/v1/messages \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "+15551234567",
    "body": "Thanks for connecting with Acme Support. Reply here any time.",
    "idempotency_key": "first-send-2026-06-07"
  }'
```

Sondea el mensaje para conocer el estado de entrega e inspecciona los registros del panel para ver el estado
del proveedor.

```bash
curl https://api.texttree.ai/api/v1/messages/$MESSAGE_ID \
  -H "Authorization: Bearer $TEXTREE_ACCESS_TOKEN"
```

## Patrón de integración de agentes

Usa las herramientas MCP para obtener contexto acotado y envíos auditados. Un agente de IA debe:

1. leer los recursos de onboarding y facturación antes de la ejecución
2. recopilar detalles explícitos de destinatario, financiamiento, marca, sitio web, almacenamiento y aprobación
3. delegar a tu aplicación o a un operador humano la aprobación final del envío cuando se requiera
4. llamar a `messages.send` o enviar mediante `/api/v1/messages` para que se ejecuten las compuertas de supresión, gasto, preparación del remitente y proveedor

Esto mantiene los flujos de trabajo de los agentes detrás de los mismos controles de producción que los envíos humanos y de API.

## Recuperación con códigos de respaldo

Los códigos de respaldo se devuelven durante el arranque de la cuenta sin interfaz o se generan en la configuración de la cuenta.
Se muestran una sola vez, se almacenan con hash y se consumen en el primer uso. Generar un nuevo
conjunto invalida los códigos existentes sin usar tras una confirmación explícita. Los intentos
de recuperación tienen límite de tasa y se registran sin almacenar los códigos sin procesar.

## Restricciones actuales de la fase alfa

- Las herramientas MCP siguen respaldadas por configuración en lugar de ser configurables por tenant
- el ejecutor predeterminado es intencionalmente simple y no es un tiempo de ejecución dinámico completo de herramientas
- no existe un visor público de registros de auditoría fuera de las superficies de operador de Phoenix y la base de datos del repositorio

