MCP y herramientas conectadas
Conecta Nessie a servidores MCP y empareja un agente externo para que pueda trabajar en Nessie en tu nombre.
Qué es MCP
El Model Context Protocol es una convención pequeña y abierta para describir herramientas a un modelo de lenguaje y para invocarlas. Un servidor declara lo que puede hacer (una lista de herramientas con nombre, cada una con un esquema JSON para sus argumentos), y un cliente descubre esa lista e invoca las herramientas en nombre del modelo. Es deliberadamente sobrio: el valor está en que una integración escrita una sola vez funcione con todos los modelos y todos los productos que hablen este protocolo.
Nessie está en los dos lados
Conviene ser precisos con esto, porque las dos mitades se confunden con facilidad y viven en rutas deliberadamente distintas.
- Saliente. Nessie es un cliente MCP. Conectas servidores que gestiona otra persona, y las herramientas que exponen pasan a ser herramientas que tus agentes pueden usar. La superficie de gestión está en
/api/mcp/*. - Entrante. Nessie también es un servidor MCP. Un agente que se ejecuta en otro sitio (Claude Code o Codex en el equipo de un desarrollador) puede llamar a tus tableros y documentos. Ese endpoint es
POST /mcp, fuera de/apia propósito, para que los dos significados opuestos no compartan un segmento de ruta.
Conectar un servidor MCP a Nessie
Entradas del catálogo e instancias
Hay dos objetos, y la distinción importa:
- Una entrada del catálogo es la definición de un servidor: su nombre, su transporte y cómo se autentica. Se escribe una vez y puede compartirse.
- Una instancia es esa entrada instalada en un ámbito concreto, con las credenciales que llegan a ella. Instalar la misma entrada para dos equipos distintos produce dos instancias.
A la mayoría de las personas no les toca ninguno de los dos directamente. La puerta de entrada en el admin es la tienda de aplicaciones en /admin/apps: explora el mismo catálogo con los datos de conexión ocultos, y Connect en una ficha crea una instancia. Los operadores que quieran los objetos en bruto usan /api/mcp/catalog y /api/mcp/instances.
Si un servidor todavía no está en el catálogo, POST /api/mcp/discover recibe una URL y devuelve lo que el servidor dice de sí mismo, y POST /api/mcp/library/import trae una entrada de la biblioteca pública de servidores. Una primera conexión también puede crearse directamente desde una URL con POST /api/apps/custom.
Transportes
Nessie se conecta a servidores remotos por HTTP. Funcionan dos transportes: HTTP en streaming (el transporte MCP actual) y el transporte HTTP+SSE, más antiguo. Elige http salvo que el servidor solo ofrezca sse.
El transporte stdio se rechaza para los conectores que tú escribes. stdio significa que el servidor MCP es un proceso local que arranca el host, y ejecutar programas arbitrarios dentro del servidor de Nessie no es algo que un operador pueda revisar de forma significativa. Los servidores que se publican solo como paquete para ejecutar en local se descartan de las importaciones de la biblioteca por el mismo motivo. Existe un valor ws en el campo de protocolo y no está implementado: una conexión que lo use falla cuando Nessie intenta abrirla.
Cómo se autentica Nessie ante el servidor
Una entrada del catálogo declara uno de cinco métodos: none, api_key, bearer, basic u oauth2.
api_key es una inyección de cabecera, y la entrada indica cuál y con qué prefijo; así, Authorization: Bearer …, X-API-Key: … y X-Auth-Token: Token … son el mismo método configurado de forma distinta. La clave se pega una sola vez con POST /api/mcp/instances/:instanceId/secret y no vuelve a ser legible nunca; ninguna respuesta de las rutas de instancias incluye una referencia a la credencial.
oauth2 tiene dos formas. Un servidor con endpoints fijos los tiene en su entrada del catálogo. Un servidor que publica metadatos estándar no necesita configurar nada: Nessie lee los documentos de recurso protegido y de servidor de autorización, y se crea a sí mismo un cliente mediante registro dinámico de clientes o mediante el documento de metadatos de ID de cliente que publica en su propia ruta well-known. En cualquier caso, el protocolo es POST /api/mcp/instances/:instanceId/oauth/start, seguido de la redirección del proveedor de vuelta a GET /api/mcp/oauth/callback. El token de estado es de un solo uso, se guarda en la base de datos y es válido durante diez minutos, y PKCE se usa siempre.
Hay una regla que sorprende a la gente: ni siquiera un propietario de la organización puede asociar un token personal u OAuth a otra persona. Una credencial compartida solo es posible para una entrada de clave de API que se haya validado como tal; cualquier otra cosa se rechaza. Una credencial que pertenece a una persona sigue perteneciendo a esa persona.
Dónde viven las credenciales
Los secretos de los conectores y los paquetes de tokens OAuth se guardan en tu propia base de datos Postgres, en sobres AES-256-GCM con un propósito concreto, bajo el anillo de claves de cifrado del despliegue, que se versiona de forma independiente, y se direccionan solo mediante referencias opacas secret_*. Deliberadamente no están en el almacén de secretos externo que guarda los demás secretos de Nessie. Un despliegue de producción que no haya configurado el almacén cifrado no arranca, en lugar de completar un flujo OAuth que luego perdería por el camino.
Hasta dónde llega una conexión
Una instancia se instala en uno de seis ámbitos: system, organization, project, team, channel o user. Ese ámbito es un techo firme sobre qué ejecuciones pueden usarla, y las concesiones solo pueden reducirlo, nunca ampliarlo; así, un conector que instalaste con tu propia cuenta no puede convertirse en silencio en uno de toda la organización.
Quién puede instalar en cada sitio sigue la misma forma: los propietarios y administradores de la organización gestionan las instalaciones en cualquier ámbito; el resto instala conectores en su propio ámbito user y puede ver las instalaciones compartidas a las que tiene acceso.
Dar una herramienta a un agente
Conectar un servidor no entrega sus herramientas a nadie. Cuando se instala una instancia, Nessie la sondea y proyecta cada herramienta que anuncia en el registro de herramientas, que es lo que el admin muestra en /admin/advanced/tools: herramientas integradas, herramientas MCP, herramientas de paquete y herramientas del ejecutor, todas en una sola lista, cada una con su origen y su estado.
Una herramienta proyectada tiene uno de tres estados: active, pending_review o disabled. Las herramientas de una instalación de ámbito compartido llegan como pending_review y hay que aprobarlas en esa página antes de que un agente las vea; las herramientas de tu propia instalación de ámbito user están activas desde el primer momento, porque la única persona expuesta eres tú. La revisión es recurrente, no una ceremonia única: si un sondeo posterior detecta que la descripción o el esquema de una herramienta ha cambiado, vuelve a pending_review y deja de ofrecerse hasta que alguien revise el cambio.
Qué agentes pueden llamar después a una herramienta activa se decide de dos formas:
- Una conexión creada desde la tienda de aplicaciones exige una concesión explícita. Un agente solo obtiene la herramienta cuando una concesión la nombra, y la concesión se comprueba contra la huella actual de la herramienta, así que una herramienta modificada necesita una decisión nueva.
- En los demás casos, la herramienta está activada por defecto para los agentes que alcanza su ámbito, y los agentes concretos se desactivan en el panel de detalle de la herramienta.
Una concesión nombra exactamente un principal (un rol o un agente, nunca ambos), y una denegación gana a una concesión. Para una conexión de ámbito user la pregunta no se plantea: cualquier agente con el que hable esa persona puede usarla, y lo único que la retiene es un interruptor de desactivación explícito.
Hay algo fácil de buscar en el lugar equivocado: /settings/accounts en el admin son las cuentas conectadas: Slack, buzones de correo, suscripciones de modelos y los enlaces OAuth a Linear, Jira, GitHub y Trello que respaldan los tableros externos. Los conectores MCP están en /admin/apps, y las herramientas que producen están en /admin/advanced/tools.
Puertas de aprobación en las llamadas a herramientas
Algunas llamadas a herramientas se detienen y esperan a una persona. Cuando eso ocurre, la ejecución no falla: la invocación se congela (el nombre de la herramienta, un hash de sus argumentos y el estado suficiente para reanudarla) y aparece una solicitud de aprobación en /api/approvals para que alguien la responda. Reanudar es idempotente, así que una aprobación duplicada no puede ejecutar la llamada dos veces. La persona que decide ve un resumen acotado de lo que se pide; los argumentos exactos y la ejecución de origen se quedan en el servidor.
Hay dos puertas distintas, y se configuran de forma diferente.
- Las puertas estructurales son una propiedad de ciertas herramientas integradas y no se pueden configurar. Enviar correo desde el buzón propio de un agente o desde uno conectado, enviar un borrador de Gmail, desconectar una cuenta de correo, crear, modificar o cancelar un evento de calendario, y una acción de navegador que escribiría en un sitio en el que el navegador no tiene sesión iniciada están todas protegidas así. Tienen una ventana de 24 horas para responder, en lugar de los 30 minutos habituales.
- Las puertas de política vienen de reglas de política sobre el par
tool/invoke. Una regla que permite una invocación puede llevarrequiresApproval, y sin una aprobación verificada la evaluación devuelveAPPROVAL_REQUIREDen lugar de ejecutar. Las reglas se evalúan primero las denegaciones y se ordenan por ámbito.
No hemos podido confirmar qué pantalla del admin crea una regla de política requiresApproval para una herramienta: el modelo de datos y la aplicación están implementados, pero no la pantalla que escribe esa regla.
Conectar un agente externo a Nessie
En la otra dirección. Nessie ejecuta un servidor MCP propio en POST /mcp, sobre HTTP en streaming, y no tiene estado: cada llamada lleva su propia credencial y resuelve a su propio actor, así que no hay ninguna sesión a la que fijar un cliente en una réplica concreta. ChatGPT, Claude, Claude Code, Codex o un agente en el portátil de alguien pueden trabajar sobre tus tableros, documentos y clientes desde dentro de la herramienta que esa persona ya usa. La guía paso a paso para cada app está en Conecta ChatGPT, Claude y otras apps de IA.
Qué es realmente una credencial emparejada
Esta es la parte que hay que entender bien, porque el modelo mental obvio (una clave de API con permisos adjuntos) es el equivocado.
Una credencial emparejada nunca es una identidad. Nombra a una persona, y cada llamada a una herramienta se ejecuta como esa persona, contra las mismas funciones de servicio a las que llaman las rutas HTTP. Por tanto, un agente no puede llegar a nada que la persona que se lo prestó no pudiera alcanzar haciendo clic. Los ámbitos solo reducen ese alcance; no existe ningún ámbito que lo amplíe.
La vigencia se vuelve a leer en cada llamada, nunca se da por buena desde el token: la revocación, la caducidad, la versión del token del usuario, su pertenencia a la organización y su rol actual. Una degradación, una desactivación o un «cierra sesión en todas partes» afectan a la siguiente llamada del agente, y no esperan a que la credencial caduque.
El token es opaco, lleva el prefijo nag1_, se guarda solo como hash SHA-256 y dura 90 días. Se rechaza con un 403 específico en cualquier ruta que no sea el endpoint de MCP: presentarlo en otro sitio no es un éxito parcial que haya que reintentar, y eso es lo que impide que «presté mis tableros a un agente» signifique «le presté mi cuenta».
Dos formas de conectar
Una app que puede abrir un navegador (ChatGPT, Claude, Claude Code, Codex) usa el perfil de autorización MCP: OAuth 2.1 con PKCE (S256), registro dinámico de clientes en POST /mcp/oauth/register, tokens de refresco e indicadores de recurso. La app envía a la persona a /settings/security, esta elige lo que la app puede hacer y a cuáles de sus equipos llega, y el navegador vuelve a la app con un código. Su token de acceso dura una hora y se renueva; la conexión dura 90 días.
Un agente de línea de comandos no controla ningún navegador ni puede alojar una URL de callback, así que se empareja con la concesión de autorización de dispositivo (RFC 8628).
- El agente llama a
POST /mcp/auth/devicecon unclientNamey losscopesque quiere. Recibe undevice_code, unuser_codecorto, unverification_uriy unverification_uri_completecon el código ya en la query, además delintervalde sondeo y unexpires_in. Imprime la URI. - Una persona abre esa URI con la sesión iniciada, en
/settings/security. Ve qué agente lo pide, en nombre de qué cuenta trabajaría, hasta cuándo y exactamente lo que podría hacer, y elige Permitir o No permitir. - El agente sondea
POST /mcp/auth/tokencon eldeviceCode, respetandoauthorization_pending,slow_down,expired_tokenyaccess_denied. Si tiene éxito, recibe{ access_token, token_type, scope, expires_at }.
En cualquier caso hay un paso humano, porque la credencial hereda los permisos de una persona, así que una persona tiene que decidir prestarlos. Aquí nada genera acceso de la nada. Conectar también se puede desactivar para toda una organización en /admin/security?tab=programs, y esa respuesta se comprueba cuando alguien permite una conexión, no cuando un agente inicia una.
Descubrimiento
Un POST /mcp sin autenticar responde 401 con una cabecera WWW-Authenticate que apunta a /.well-known/oauth-protected-resource (RFC 9728), que nombra este origen como servidor de autorización; sus metadatos en /.well-known/oauth-authorization-server (RFC 8414) nombran los endpoints de registro, autorización, token y revocación. Esa cadena es todo lo que necesita un cliente una vez tiene la dirección. Para encontrar la dirección a partir de un dominio, un agente lee /.well-known/ai-catalog.json, que nombra la Server Card en /mcp/server-card (MCP Server Cards, SEP-2127). Los endpoints de la concesión de dispositivo aparecen en el documento de recurso protegido bajo x-nessie-device-authorization.
Un despliegue también puede responder en una segunda dirección más corta: https://nessie.works/mcp de Nessie Cloud se reenvía a la API, y un cliente que llegó por esa vía recibe esa dirección como recurso, mientras que el inicio de sesión sigue en la API. Una redirección no serviría, porque un cliente rechaza metadatos que nombren una dirección distinta de la que se le dio. El operador enumera estos orígenes en NESSIE_MCP_ALIAS_ORIGINS.
Ámbitos y herramientas
Los ámbitos son deliberadamente gruesos: un ámbito que nadie sabe explicar es un ámbito que nadie configura bien. Una conexión que llega a más de un equipo los enumera con nessie_team_list, y cada una de las demás herramientas indica entonces su teamId.
| Ámbito | Alcanza |
|---|---|
boards_read | Proyectos, tableros y tickets, con sus comentarios, archivos, etiquetas, tipos y listas de verificación |
boards_write | Crear, editar y mover tickets, y todo lo que contienen |
documents_read | Espacios de conocimiento, documentos y hojas de cálculo |
documents_write | Redactarlos y editarlos, y pedir publicar uno |
clients_read | La bandeja de entrada de clientes, los contactos, las listas de contactos, los boletines y los formularios de contacto |
clients_write | Notas, tomar, asignar y cerrar conversaciones, listas de contactos y preparación de boletines |
clients_send | Todo lo que recibe un cliente: una respuesta, un primer correo o un SMS. Nunca se marca salvo que la persona lo marque |
website_tools | Las herramientas de página del sitio web registrado de tu equipo, manejadas en un navegador alojado que puedes controlar. Nunca se marca salvo que la persona lo marque |
Una llamada sin el ámbito que necesita vuelve como resultado de herramienta que nombra el ámbito que hay que pedir, no como error de transporte, para que el modelo pueda informar de algo útil en lugar de reintentar contra un muro.
No hay una familia de herramientas aparte para los gestores de tareas externos. Un tablero es un tablero, tanto si sus tareas se originan en Nessie como si se replican desde Linear, Jira, GitHub o Trello, así que un único conjunto de herramientas cubre ambos, y cada tarea indica de dónde viene. Lo que cambia es la escritura: un tablero replicado desde una fuente de solo lectura rechaza una escritura con palabras, indicando al agente que el ticket lo tiene el otro sistema y que reintentar no servirá de nada.
Publicar un documento es una aprobación, nunca un ámbito
Los agentes redactan; una persona publica. Esa regla se aplica a los agentes propios de Nessie rechazando sin más a un actor agente, pero una credencial emparejada se resuelve como una persona, así que ese rechazo no puede detectarla. La puerta tiene que estar en otro sitio.
Por eso nessie_doc_publish no publica. Abre una aprobación knowledge.page.publish, la misma que abre un agente de Nessie, y devuelve { status: "awaiting_approval", approvalId }. Si se consulta de nuevo, devuelve la misma solicitud en lugar de abrir una segunda. La decisión se toma como se toma cualquier decisión de publicación en Nessie: una persona, sobre ese documento, en el momento en que existe.
Deliberadamente no hay ningún ámbito de publicación. Hubo uno (una casilla marcada al emparejar que decía que este agente podía publicar), y se retiró. Decidía, una vez y durante noventa días, una pregunta que el producto plantea por documento en todas partes, y lo decidía antes de que el documento existiera, de modo que la persona que marcaba la casilla no podía saber qué estaba aceptando publicar. nessie_doc_publish necesita documents_write, porque pedir no es gratis: lee la página y pone una decisión delante de alguien, pero ese ámbito no concede nada sobre la publicación.
En la solicitud se registran dos identidades, y la distinción es determinante. El solicitante es la credencial, nunca la persona en cuyo nombre actúa. El aprobador requerido es esa persona, y solo ella puede responder. Si la solicitud nombrara a la persona como solicitante, la regla que impide aprobar la propia solicitud descalificaría a la única persona con derecho a decidir.
Ver y revocar lo que está emparejado
Los agentes emparejados de cada persona aparecen en /settings/security, con una etiqueta y un control de revocación para cada uno. Un propietario o administrador de la organización ve todas las credenciales de la organización en /admin/security?tab=programs (cómo se llama cada una, qué puede hacer, si sigue vigente y en nombre de qué cuenta trabaja) y puede revocar cualquiera. La lista personal es solo para uno mismo: una lista de credenciales vigentes es una lista de puntos de apoyo, no una lectura general.
Las escrituras hechas con una credencial se atribuyen a la persona que la presta y llevan el id de la credencial en los metadatos de auditoría, así que el registro puede distinguir una edición propia de una que hizo su agente por ella.
Lo que todavía no está disponible
Lo decimos de forma explícita, porque la distancia entre las capacidades de un protocolo y las de un servidor concreto es donde suele fallar la documentación:
- El chat, los canales, las ejecuciones y la gestión de agentes no se exponen por MCP.
- Un programa prepara un boletín y una persona lo envía: nada envía, programa ni borra una campaña, y el propio correo se escribe en el diseñador.
- Vincular y fusionar contactos, los cambios de esquema del CRM, las importaciones y la configuración de canales siguen en manos de una persona en el navegador.
- El interruptor de conexión es un ajuste a nivel de organización. Los ajustes a nivel de equipo y las excepciones personales no se pueden definir hoy desde un equipo ni por una persona.