nessie

MCP e ferramentas ligadas

Ligar o Nessie a servidores MCP e emparelhar um agente externo para que possa trabalhar no Nessie em nome do utilizador.

O que é o MCP

O Model Context Protocol é uma convenção pequena e aberta para descrever ferramentas a um modelo de linguagem e para as invocar. Um servidor declara o que sabe fazer — uma lista de ferramentas com nome, cada uma com um esquema JSON para os respetivos argumentos — e um cliente descobre essa lista e invoca as ferramentas em nome do modelo. É deliberadamente sóbrio: o valor está em que uma integração escrita uma única vez funciona com todos os modelos e todos os produtos que falam este protocolo.

O Nessie está dos dois lados

Vale a pena ser preciso nisto, porque as duas metades são fáceis de confundir e vivem em caminhos deliberadamente diferentes.

  • Saída. O Nessie é um cliente MCP. Liga-se a servidores que outra pessoa gere, e as ferramentas que esses servidores expõem passam a poder ser usadas pelos seus agentes. A superfície de gestão é /api/mcp/*.
  • Entrada. O Nessie é também um servidor MCP. Um agente que corre noutro local — o Claude Code ou o Codex no computador de um programador — pode aceder aos seus quadros e documentos. Esse endpoint é POST /mcp, fora de /api de propósito, para que os dois significados opostos não fiquem separados por um único segmento de caminho.

Ligar um servidor MCP ao Nessie

Entradas do catálogo e instâncias

Há dois objetos, e a distinção importa:

  • Uma entrada do catálogo é a definição de um servidor — o seu nome, o seu transporte, a forma como se autentica. É escrita uma única vez e pode ser partilhada.
  • Uma instância é essa entrada instalada num determinado âmbito, com as credenciais que lhe dão acesso. Instalar a mesma entrada para duas equipas diferentes produz duas instâncias.

A maioria das pessoas nunca lida diretamente com nenhum dos dois. A porta de entrada na admin é a loja de aplicações em /admin/apps: navega pelo mesmo catálogo com os detalhes de ligação ocultos, e Ligar numa listagem cria uma instância. Os operadores que querem os objetos em bruto usam /api/mcp/catalog e /api/mcp/instances.

Se um servidor ainda não estiver no catálogo, POST /api/mcp/discover recebe um URL e devolve o que o próprio servidor diz sobre si, e POST /api/mcp/library/import importa uma entrada da biblioteca pública de servidores. Uma ligação de primeira execução também pode ser criada diretamente a partir de um URL com POST /api/apps/custom.

Transportes

O Nessie liga-se a servidores remotos através de HTTP. Funcionam dois transportes: HTTP streamable (o transporte atual do MCP) e o transporte HTTP+SSE, mais antigo. Usa-se http, salvo se o servidor só oferecer sse.

O transporte stdio é recusado para os conectores que criou. Em stdio, o servidor MCP é um processo local que o host arranca, e executar programas arbitrários dentro do servidor do Nessie não é algo que um operador consiga rever de forma significativa. Os servidores publicados apenas como pacote para correr localmente ficam fora das importações da biblioteca pelo mesmo motivo. Existe um valor ws no campo de protocolo, que não está implementado — uma ligação que o use falha quando o Nessie tenta abri-la.

Como o Nessie se autentica no servidor

Uma entrada do catálogo declara um de cinco métodos: none, api_key, bearer, basic ou oauth2.

api_key é injeção de cabeçalho, e a entrada indica qual o cabeçalho e que prefixo usar — por isso Authorization: Bearer …, X-API-Key: … e X-Auth-Token: Token … são todos o mesmo método, configurado de maneira diferente. A chave em si é colada uma única vez com POST /api/mcp/instances/:instanceId/secret e nunca mais pode ser lida; nenhuma resposta das rotas de instâncias inclui uma referência a credenciais.

oauth2 tem duas formas. Um servidor com endpoints fixos tem-nos na respetiva entrada do catálogo. Um servidor que publica metadados padrão não precisa de nada configurado: o Nessie lê os documentos de recurso protegido e de servidor de autorização, e cria para si próprio um cliente através de registo dinâmico de clientes ou através do documento de metadados de ID de cliente que publica no seu próprio caminho well-known. Em qualquer dos casos, o handshake é POST /api/mcp/instances/:instanceId/oauth/start, seguido do redirecionamento do fornecedor de volta para GET /api/mcp/oauth/callback. O token de estado é de utilização única, fica guardado na base de dados e é válido durante dez minutos, e o PKCE é sempre usado.

Há uma regra que surpreende as pessoas: nem sequer um proprietário de organização pode associar um token pessoal ou OAuth a outra pessoa. Uma credencial partilhada só é possível para uma entrada de chave de API que tenha sido validada como tal; tudo o resto é recusado. Uma credencial que pertence a uma pessoa continua a pertencer a essa pessoa.

Onde ficam as credenciais

Os segredos dos conectores e os pacotes de tokens OAuth são guardados na sua própria base de dados Postgres, em envelopes AES-256-GCM de finalidade específica, sob o anel de chaves de cifragem da implementação, que tem versões independentes, e só são endereçados por referências opacas secret_*. Ficam deliberadamente fora do cofre de segredos externo que guarda os outros segredos do Nessie. Uma implementação de produção que não tenha configurado o armazenamento cifrado recusa-se a arrancar, em vez de concluir um handshake OAuth que depois perderia.

Onde chega uma ligação

Uma instância é instalada num de seis âmbitos: system, organization, project, team, channel ou user. Esse âmbito é um limite rígido sobre as execuções que a podem usar, e as concessões só o podem restringir ainda mais, nunca alargar — por isso um conector que instalou com a sua própria conta não se pode tornar silenciosamente um conector de toda a organização.

Quem pode instalar em cada âmbito segue a mesma lógica: os proprietários e administradores da organização gerem as instalações em qualquer âmbito; todos os outros instalam conectores no seu próprio âmbito user e podem ver as instalações partilhadas a que têm direito de aceder.

Dar uma ferramenta a um agente

Ligar um servidor não entrega as suas ferramentas a ninguém. Quando uma instância é instalada, o Nessie sonda-a e projeta cada ferramenta que ela anuncia para o registo de ferramentas, que é o que a admin mostra em /admin/advanced/tools — ferramentas incorporadas, ferramentas de MCP, ferramentas de pacotes e ferramentas do executor numa única lista, cada uma com a sua origem e o seu estado.

Uma ferramenta projetada tem um de três estados: active, pending_review ou disabled. As ferramentas de uma instalação de âmbito partilhado chegam como pending_review e têm de ser aprovadas nessa página antes de um agente as ver; as ferramentas da sua própria instalação de âmbito user ficam ativas de imediato, porque a única pessoa exposta é o próprio. A revisão é recorrente, não uma formalidade única: se uma sondagem posterior verificar que a descrição ou o esquema de uma ferramenta mudou, a ferramenta volta a pending_review e deixa de ser oferecida até alguém analisar a alteração.

Quais os agentes que podem depois invocar uma ferramenta ativa é decidido de duas formas:

  • Uma ligação criada através da loja de aplicações exige uma concessão explícita. Um agente só obtém a ferramenta quando uma concessão a indica pelo nome, e a concessão é verificada contra a impressão digital atual da ferramenta, pelo que uma ferramenta alterada precisa de uma nova decisão.
  • Caso contrário, a ferramenta fica ativa por predefinição para os agentes ao alcance do seu âmbito, e os agentes individuais são desativados no painel de detalhe da ferramenta.

Uma concessão indica exatamente um principal — um papel ou um agente, nunca os dois —, e uma recusa prevalece sobre uma autorização. Numa ligação de âmbito user a questão nem se coloca: qualquer agente com quem essa pessoa fale pode usá-la, e um desligar explícito é a única coisa que a impede.

Uma coisa fácil de procurar no sítio errado: /settings/accounts na admin são as contas ligadas — Slack, caixas de correio, subscrições de modelos e as ligações OAuth ao Linear, Jira, GitHub e Trello que suportam os quadros externos. Os conectores MCP estão em /admin/apps, e as ferramentas que produzem estão em /admin/advanced/tools.

Controlos de aprovação nas chamadas de ferramentas

Algumas chamadas de ferramentas param e aguardam uma pessoa. Quando isso acontece, a execução não falha: a invocação fica congelada — o nome da ferramenta, um hash dos respetivos argumentos e o estado suficiente para retomar — e um pedido de aprovação aparece em /api/approvals para que alguém o responda. Retomar é idempotente, por isso uma aprovação duplicada não consegue executar a chamada duas vezes. A pessoa que decide vê um resumo limitado do que está a ser pedido; os argumentos exatos e a execução de origem ficam do lado do servidor.

Existem dois controlos distintos, e são configurados de forma diferente.

  • Os controlos estruturais são uma propriedade de certas ferramentas incorporadas e não são configuráveis. Enviar correio a partir da caixa de correio de um agente ou de uma caixa ligada, enviar um rascunho do Gmail, desligar uma conta de correio, criar, alterar ou cancelar um evento de calendário, e uma ação no navegador que escrevesse num site em que o navegador não tem sessão iniciada, estão todos controlados desta forma. Dispõem de uma janela de 24 horas para serem respondidos, em vez das habituais 30 minutos.
  • Os controlos de política vêm de regras de política no par tool/invoke. Uma regra que permite uma invocação pode ter requiresApproval, e sem uma aprovação verificada a avaliação devolve APPROVAL_REQUIRED em vez de executar. As regras são avaliadas primeiro as recusas e ordenadas por âmbito.

Não conseguimos confirmar qual o ecrã da admin que cria uma regra de política requiresApproval para uma ferramenta — o modelo de dados e a aplicação estão ambos em vigor, mas não foi possível confirmar o ecrã que escreve essa regra.


Ligar um agente externo ao Nessie

A outra direção. O Nessie executa um servidor MCP próprio em POST /mcp, sobre HTTP streamable, e é sem estado: cada chamada transporta a sua própria credencial e resolve o seu próprio ator, por isso não há nenhuma sessão à qual fixar um cliente numa determinada réplica. O ChatGPT, o Claude, o Claude Code, o Codex ou um agente no portátil de alguém podem trabalhar nos seus quadros, documentos e clientes a partir de dentro da ferramenta que essa pessoa já usa. O passo a passo para cada aplicação está em Ligar o ChatGPT, o Claude e outras aplicações de IA.

O que é, de facto, uma credencial emparelhada

Esta é a parte a perceber bem, porque o modelo mental óbvio — uma chave de API com permissões associadas — é o errado.

Uma credencial emparelhada nunca é uma identidade. Identifica uma pessoa, e cada chamada de ferramenta é executada como essa pessoa, contra as mesmas funções de serviço que as rotas HTTP chamam. Um agente não consegue, portanto, aceder a nada que a pessoa que o emprestou não conseguisse aceder ao clicar. Os âmbitos só restringem esse alcance; não existe nenhum âmbito que o alargue.

A validade é reavaliada em cada chamada, nunca confiada ao token: revogação, expiração, a versão de token do utilizador, a sua pertença à organização e o seu papel atual. Uma despromoção, uma desativação ou um «terminar sessão em todo o lado» produzem efeito na chamada seguinte do agente, e não na expiração da credencial.

O token é opaco, com o prefixo nag1_, guardado apenas como hash SHA-256, e é válido durante 90 dias. É recusado com um 403 específico em qualquer rota que não seja o endpoint MCP — apresentá-lo noutro sítio não é um êxito parcial que se deva voltar a tentar, e é isso que impede que «emprestei aos agentes os meus quadros» signifique «emprestei-lhes a minha conta».

Duas formas de ligar

Uma aplicação que consegue abrir um navegador — ChatGPT, Claude, Claude Code, Codex — usa o perfil de autorização MCP: OAuth 2.1 com PKCE (S256), registo dinâmico de clientes em POST /mcp/oauth/register, tokens de atualização e indicadores de recurso. A aplicação envia a pessoa para /settings/security, esta escolhe o que a aplicação pode fazer e a que equipas suas tem acesso, e o navegador regressa à aplicação com um código. O token de acesso dura uma hora e é renovado; a ligação dura 90 dias.

Um agente de linha de comandos não controla nenhum navegador e não consegue alojar um URL de callback, por isso emparelha-se com a concessão de autorização por dispositivo (RFC 8628).

  1. O agente chama POST /mcp/auth/device com um clientName e os scopes que pretende. Recebe de volta um device_code, um user_code curto, um verification_uri e um verification_uri_complete com o código já incluído no query string, além do interval de sondagem e de um expires_in. Imprime o URI.
  2. Uma pessoa abre esse URI com sessão iniciada, em /settings/security. Vê qual o agente que pede acesso, em nome de qual conta funcionaria, até quando, e exatamente o que poderia fazer — e escolhe Permitir ou Não permitir.
  3. O agente consulta POST /mcp/auth/token com o deviceCode, respeitando authorization_pending, slow_down, expired_token e access_denied. Em caso de sucesso, recebe { access_token, token_type, scope, expires_at }.

Em qualquer dos casos há um passo humano, porque a credencial herda os direitos de uma pessoa, e por isso uma pessoa tem de optar por a emprestar. Nada aqui cria acesso do nada. Ligar também pode ser desativado para uma organização inteira em /admin/security?tab=programs, e essa resposta é verificada quando alguém permite uma ligação, e não quando um agente a inicia.

Descoberta

Um POST /mcp sem autenticação responde com 401 e com um cabeçalho WWW-Authenticate que aponta para /.well-known/oauth-protected-resource (RFC 9728), o qual indica esta origem como servidor de autorização; os respetivos metadados em /.well-known/oauth-authorization-server (RFC 8414) indicam os endpoints de registo, autorização, token e revogação. Essa cadeia é tudo o que um cliente precisa depois de ter o endereço. Para encontrar o endereço a partir de um domínio, um agente lê /.well-known/ai-catalog.json, que indica o Server Card em /mcp/server-card (MCP Server Cards, SEP-2127). Os endpoints da concessão por dispositivo estão listados no documento de recurso protegido, em x-nessie-device-authorization.

Uma implementação pode também responder num segundo endereço, mais curto: o https://nessie.works/mcp do Nessie Cloud é encaminhado para a API, e um cliente que chegou por essa via recebe esse endereço de volta como recurso, ficando o início de sessão no da API. Um redirecionamento não serviria, porque um cliente recusa metadados que indiquem outro endereço que não aquele que lhe foi dado. O operador indica estas origens em NESSIE_MCP_ALIAS_ORIGINS.

Âmbitos e ferramentas

Os âmbitos são deliberadamente grosseiros — um âmbito que ninguém consegue explicar é um âmbito que ninguém configura corretamente. Uma ligação que chega a mais de uma equipa lista-as com nessie_team_list, e cada outra ferramenta indica depois o respetivo teamId.

ÂmbitoDá acesso a
boards_readProjetos, quadros e tarefas, com os respetivos comentários, ficheiros, etiquetas, tipos e listas de verificação
boards_writeCriar, editar e mover tarefas, e tudo o que neles existe
documents_readEspaços de conhecimento, documentos e folhas de cálculo
documents_writeRedigir e editar esses documentos, e pedir a publicação de um deles
clients_readA caixa de entrada de clientes, contactos, listas de contactos, newsletters e formulários de contacto
clients_writeNotas, assumir, atribuir e fechar conversas, listas de contactos e preparação de newsletters
clients_sendTudo o que um cliente recebe: uma resposta, um primeiro email ou uma mensagem de texto. Nunca vem marcado por predefinição; só fica ativo se a pessoa o marcar
website_toolsAs ferramentas de página do site registado pela sua equipa, operadas num navegador alojado que pode controlar. Nunca vem marcado, a menos que a pessoa o marque

Uma chamada sem o âmbito de que precisa regressa como resultado de ferramenta que indica o âmbito a pedir, e não como erro de transporte, para que o modelo consiga comunicar algo útil em vez de repetir a tentativa contra um muro.

Não existe uma família separada de ferramentas para os sistemas externos de acompanhamento. Um quadro é um quadro, quer as suas tarefas tenham origem no Nessie quer sejam espelhadas do Linear, Jira, GitHub ou Trello, por isso um único conjunto de ferramentas cobre ambos, e cada tarefa indica de onde vem. A diferença está na escrita: um quadro espelhado de uma origem só de leitura recusa uma escrita com uma mensagem explícita, a dizer ao agente que a tarefa pertence ao outro sistema e que repetir a tentativa não resolve.

Publicar um documento é uma aprovação, nunca um âmbito

Os agentes redigem; uma pessoa publica. Essa regra é aplicada aos agentes do próprio Nessie ao recusar, sem mais, um ator que seja agente — mas uma credencial emparelhada resolve-se como pessoa, pelo que essa recusa não a consegue apanhar. O controlo tem de estar noutro lado.

Por isso, nessie_doc_publish não publica. Abre uma aprovação knowledge.page.publish — a mesma que um agente do Nessie abre — e devolve { status: "awaiting_approval", approvalId }. Consultar de novo devolve o mesmo pedido, em vez de abrir um segundo. A decisão é tomada da mesma forma que todas as outras decisões de publicação no Nessie: por uma pessoa, sobre esse documento, no momento em que ele existe.

Deliberadamente, não existe um âmbito de publicação. Existiu um — uma marcação feita no emparelhamento a dizer que este agente pode publicar —, e foi retirado. Decidia, uma vez e durante noventa dias, uma questão que o produto pergunta por documento em todo o lado, e decidia-a antes de o documento existir, pelo que a pessoa que a marcava não conseguia saber o que estava a aprovar para publicação. nessie_doc_publish exige documents_write, porque pedir não é gratuito — lê a página e coloca uma decisão diante de alguém —, mas esse âmbito não concede nada sobre a publicação.

Duas identidades ficam registadas no pedido, e a distinção é determinante. O solicitante é a credencial, nunca a pessoa em nome de quem atua. O aprovador exigido é essa pessoa, e só ela pode responder. Se o pedido indicasse a pessoa como solicitante, a regra que impede que alguém aprove o seu próprio pedido excluiria precisamente a única pessoa com direito a decidir.

Ver e revogar o que está emparelhado

As credenciais emparelhadas de uma pessoa estão listadas em /settings/security, com um rótulo e um controlo de revogação para cada uma. Um proprietário ou administrador da organização vê todas as credenciais da organização em /admin/security?tab=programs — como se chama cada uma, o que pode fazer, se está ativa e em nome de que conta atua — e pode revogar qualquer uma delas. A lista pessoal é apenas para o próprio: uma lista de credenciais ativas é uma lista de pontos de apoio, não uma leitura geral.

As escritas feitas através de uma credencial são atribuídas à pessoa que a empresta e levam o identificador da credencial nos metadados de auditoria, para que o registo consiga distinguir uma edição pessoal de uma que o agente fez em nome da pessoa.

O que ainda não está disponível

Sendo explícitos, porque a diferença entre as capacidades de um protocolo e as de um determinado servidor é onde a documentação costuma falhar:

  • O chat, os canais, as execuções e a gestão de agentes não são expostos através de MCP.
  • Um programa prepara uma newsletter e uma pessoa a envia: nada envia, agenda ou apaga uma campanha, e o próprio email é escrito no designer.
  • A associação e a fusão de contactos, as alterações ao esquema do CRM, as importações e a configuração de canais continuam a cargo de uma pessoa, no navegador.
  • A opção que permite ligar é uma definição ao nível da organização. As substituições ao nível da equipa e pessoais não são algo que uma equipa ou uma pessoa consiga definir hoje.