8 min de leitura

Um rebuild do servidor MCP redefine a sessão do agente?

Defina quando um rebuild de servidor MCP precisa atualizar os metadados das ferramentas, substituir a identidade executável e invalidar a autorização do agente durante uma sessão ativa.

Um rebuild do servidor MCP redefine a sessão do agente?

A recompilação de um servidor MCP local não é um único evento. Ela pode alterar o catálogo de ferramentas que o agente vê, substituir o código que trata as chamadas ou mudar a autoridade aprovada por uma pessoa. Tratar essas mudanças como uma única «atualização» genérica produz as duas falhas mais importantes: agentes chamam ferramentas usando esquemas desatualizados, ou código novo herda a permissão concedida ao código antigo.

A regra prática é simples: atualize os metadados quando o contrato anunciado mudar, substitua a identidade executável quando o código que pode ser executado mudar e redefina a autorização quando a autoridade aprovada mudar. Essas três ações costumam ocorrer juntas depois de um rebuild, mas não significam a mesma coisa. Um host que as separa consegue manter uma tarefa longa do agente em andamento sem ampliar a confiança silenciosamente.

Um rebuild tem três efeitos separados

Um rebuild pode alterar metadados, identidade executável e estado de autorização de forma independente. Deixe cada aspecto explícito na arquitetura, porque atualizar a lista de ferramentas não prova que o executável permaneceu igual, e uma caixa de aprovação não informa ao agente que seu esquema em cache ficou desatualizado.

Metadados de ferramentas são a descrição exposta por tools/list: nomes e descrições das ferramentas, esquemas de entrada, esquemas de saída quando fornecidos e anotações. É isso que o agente e o host usam para decidir se uma chamada está disponível e como formá-la.

Identidade executável responde a outra pergunta: qual código receberá esta chamada agora? Para um servidor local, a resposta pode incluir um binário compilado, um arquivo de entrada interpretado, um lockfile, uma versão do runtime, o digest de uma imagem de contêiner ou a configuração de um supervisor. Um nome de exibição como payments-dev não é uma identidade. Um caminho como /Users/dev/work/payments/dist/server.js também não.

Estado de autorização registra o que alguém aprovou e para quem. Uma pessoa pode aprovar um processo de agente para uma execução, aprovar cada chamada de ferramenta individualmente ou aprovar uma conexão com o servidor. Cada modelo precisa de um escopo claro. Se o sujeito aprovado mudar, a aprovação não deve acompanhá-lo apenas porque o nome da ferramenta permaneceu igual.

As equipes misturam essas fronteiras porque o ciclo de desenvolvimento costuma parecer uma ação única:

  1. Editar um handler.
  2. Fazer o build ou salvar.
  3. Reiniciar um servidor local.
  4. Continuar a sessão do agente.

Esse ciclo muda mais de uma coisa. Um handler pode ganhar um efeito colateral sem alterar o nome ou o esquema. Um esquema pode adicionar um campo environment sem alterar ainda nenhum byte executável. Um supervisor pode substituir um processo filho enquanto o processo pai mantém uma conexão stdio aberta. Se tudo isso for chamado de «hot reload», não haverá uma regra confiável para definir o que o host precisa invalidar.

Use três termos no código e nas discussões operacionais: revisão do catálogo, época de execução e escopo de aprovação. Uma revisão do catálogo descreve o que as ferramentas afirmam ser. Uma época de execução identifica o código atualmente capaz de agir. O escopo de aprovação descreve o sujeito exato e a duração de uma concessão. Os nomes importam pouco. Manter os conceitos separados é essencial.

Os metadados precisam ser atualizados quando o contrato anunciado mudar

Atualize os metadados sempre que um rebuild alterar algo que o cliente possa usar para selecionar, combinar, exibir ou restringir uma chamada. Isso inclui adicionar ou remover uma ferramenta, mas os casos difíceis envolvem mudanças em uma ferramenta existente.

A especificação MCP Tools fornece aos servidores notifications/tools/list_changed para avisar aos clientes que a lista de ferramentas mudou. É útil, mas deliberadamente simples: a notificação diz que a lista mudou, não o que mudou nem se o cliente já a buscou novamente. Um servidor que a emite deve esperar que o cliente execute tools/list outra vez. Um cliente não deve presumir que todo servidor ou host reagirá imediatamente, especialmente em implementações que usam cache de forma agressiva.

Atualize quando qualquer um destes campos mudar:

  • Um nome de ferramenta for adicionado, removido ou renomeado.
  • A descrição mudar de uma forma que altere o uso pretendido ou os efeitos colaterais.
  • O esquema de entrada mudar, incluindo valores padrão, valores de enumeração, campos obrigatórios, limites e formato do objeto.
  • O esquema de saída mudar e o agente usar esse resultado para tomar sua próxima decisão.
  • Uma anotação, um título ou um campo de apresentação mudar de uma forma que afete a revisão feita pelo host.

O último item exige avaliação. O esquema MCP descreve anotações como dicas, e a especificação alerta os clientes para não tomar decisões de segurança com base em anotações recebidas de um servidor não confiável. Esse alerta está correto. Um readOnlyHint pode ajudar o host a apresentar uma chamada, mas não pode transformar uma escrita em leitura. Se um servidor local mudar readOnlyHint de true para false, atualize o catálogo para que a visualização humana permaneça correta. Não deixe esse campo decidir se a chamada receberá credenciais.

Uma mudança de esquema merece mais cuidado do que muitas equipes dedicam a ela. Considere uma ferramenta que começou com este contrato:

{
  "name": "publish_preview",
  "inputSchema": {
    "type": "object",
    "required": ["branch"],
    "properties": {
      "branch": { "type": "string" }
    },
    "additionalProperties": false
  }
}

Um desenvolvedor recompila a ferramenta e adiciona este campo opcional:

"target": {
  "type": "string",
  "enum": ["preview", "production"],
  "default": "preview"
}

Isso pode parecer inofensivo. Ainda assim, o agente pode ter armazenado o primeiro esquema em cache, o host pode exibir um cartão de aprovação sem o destino, e a implementação pode conter um bug que trata um valor omitido como production. A resposta correta não é apenas aceitar o campo extra. Atualize o catálogo, deixe o valor padrão visível na tela de revisão e teste um argumento omitido contra o código em execução.

Uma atualização de metadados basta quando o executável não mudou e o escopo de aprovação existente continua válido. Isso ocorre quando um servidor gera ferramentas a partir de dados remotos e publica uma nova lista enquanto o mesmo código continua em execução. Também ocorre quando um host corrige uma documentação fora do processo do servidor. Não reinicie uma sessão apenas para corrigir um erro de digitação na descrição.

Mas não use a atualização de metadados como substituta de uma fronteira de execução. Ela informa ao agente o que o servidor diz que pode fazer. Não informa o que o servidor realmente fará.

Um executável alterado precisa de uma nova identidade

Substitua a identidade do servidor sempre que uma nova imagem de código, configuração de runtime ou conjunto de dependências puder tratar chamadas. Isso inclui um binário reiniciado, um módulo JavaScript recarregado, uma nova imagem de contêiner, um ambiente de interpretador alterado e um script wrapper alterado que encaminhe chamadas para outro programa.

O erro que vejo com mais frequência é vincular a confiança a uma linha de comando. Um host armazena algo como:

server = "inventory"
command = "node"
args = ["/work/inventory/server.js"]

Depois presume que o servidor continua sendo o mesmo até a configuração mudar. Não continua. O processo node pode carregar um server.js diferente depois de um rebuild. Esse arquivo pode resolver uma árvore de dependências diferente. O arquivo pode até permanecer byte a byte idêntico enquanto um addon nativo, uma variável de ambiente ou um wrapper de shell direciona a execução para outro lugar.

Você não precisa de uma impressão digital universal perfeita para melhorar isso. Precisa de uma identidade com escopo declarado e uma regra conservadora de invalidação. Para um servidor local de desenvolvimento, crie um registro de execução no momento da inicialização:

{
  "serverLabel": "inventory-local",
  "launchCommand": ["node", "/work/inventory/dist/server.js"],
  "entryDigest": "sha256:9e4c...71af",
  "lockfileDigest": "sha256:344b...0d19",
  "runtime": "node 22.14.0",
  "workingDirectory": "/work/inventory",
  "epoch": "01JQ7R4S4S0QJ7GZP1S2",
  "processId": 48192
}

Os digests impedem que um caminho se passe por identidade. O runtime e o diretório de trabalho explicam como o host resolveu o ponto de entrada. A época fornece um identificador único para cada reinício, mesmo que o artefato recompilado produza o mesmo digest. O ID do processo ajuda uma pessoa operadora a investigar, mas não é uma identidade, pois os sistemas operacionais reutilizam esses IDs.

Para um servidor compilado, calcule o hash do executável real depois que o build terminar. Para um servidor de scripts, calcule no mínimo o hash do ponto de entrada e do lockfile de dependências. Se o runtime carregar código fora desse lockfile, inclua a árvore de pacotes resolvida ou execute um artefato empacotado. Se um script de shell iniciar o servidor real, calcule o hash do script e do artefato filho. Uma identidade que ignora o dispatcher apenas prova que o programa errado permaneceu inalterado.

No macOS, esta verificação básica fornece um registro repetível antes de iniciar um servidor local:

shasum -a 256 dist/server.js package-lock.json

A saída típica tem um digest e um caminho em cada linha:

9e4c1b2d8f3a6d...71af  dist/server.js
344bb81b6c09de...0d19  package-lock.json

Não calcule esse digest depois que o agente já tiver retomado o trabalho. Capture-o no início do processo, associe-o à época do servidor e registre-o ao lado de cada decisão de autorização. Caso contrário, uma trilha de auditoria poderá provar apenas que algum arquivo existiu em algum momento.

Um rebuild que muda o código, mas preserva o mesmo catálogo de ferramentas, ainda precisa de uma atualização de identidade. Imagine que get_invoice mantenha nome, esquema, descrição e anotação somente leitura. O handler recompilado agora envia cada número de fatura para um endpoint externo de depuração antes de devolver a mesma fatura. Os metadados não mudaram. A autoridade mudou.

O inverso também pode acontecer. Um servidor em execução pode publicar um conjunto diferente de ferramentas específicas de um tenant com base em uma configuração atualizada, enquanto sua identidade executável permanece fixa. Atualize os metadados, mantenha a época e decida a autorização com base em saber se o novo catálogo ultrapassa o escopo aprovado.

A autorização precisa acompanhar a época de execução

Invalide a autorização quando a época de execução do servidor mudar, a menos que a autorização cubra explicitamente um publicador confiável e um canal de atualização definido. Para servidores locais recompilados, essa exceção costuma dar mais trabalho do que vale.

É comum defender a manutenção da aprovação entre rebuilds porque o desenvolvimento se torna irritante de outra forma. O argumento tem fundamento: exigir uma aprovação a cada salvamento tornaria o controle inútil. A resposta não é tornar a aprovação eterna. É vinculá-la à unidade correta.

Uma concessão prática de aprovação pode vincular estes campos:

{
  "agentRun": "run_01JQ7R1",
  "serverLabel": "inventory-local",
  "executionEpoch": "01JQ7R4S4S0QJ7GZP1S2",
  "toolScope": ["inventory_lookup", "inventory_adjust"],
  "credentialScope": ["inventory-api-staging"],
  "issuedAt": "2026-07-22T14:31:08Z",
  "expiresWhen": "agent-run-ends"
}

Essa concessão diz algo que uma pessoa revisora consegue entender: esta execução do agente pode usar estas ferramentas por meio desta instância exata do servidor, com este escopo de credenciais nomeado. Um servidor reiniciado recebe uma nova época. O host rejeita a concessão antiga antes de injetar uma credencial e solicita uma nova aprovação se a chamada ainda precisar de autoridade.

Não vincule a concessão apenas aos nomes das ferramentas. Nomes são uma convenção de interface. Um rebuild pode transformar inventory_adjust de «alterar uma quantidade em staging» em «chamar um endpoint de produção selecionado por uma variável de ambiente». Mesmo que o agente continue chamando o mesmo nome, o host precisa perceber que o executável que trata esse nome mudou.

A mesma regra vale para um wrapper do lado do agente. Se o agente inicia um servidor MCP local por meio de um launcher que se recompila ou se reescreve, o launcher deve fazer parte do registro de identidade. Um wrapper malicioso ou defeituoso pode preservar todos os nomes de ferramentas visíveis ao usuário enquanto redireciona as chamadas para outro programa.

Há casos em que uma aprovação pode sobreviver a uma atualização de código, mas eles exigem mais estrutura do que um build local costuma ter. Por exemplo, uma organização pode aprovar artefatos assinados por um publicador nomeado, restritos a um canal de implantação, com uma política de versão verificada, escopo fixo de credenciais e um processo separado para revisar mudanças de permissão. Isso é gerenciamento de releases. Não finja que um observador de arquivos e um diretório de desenvolvimento sem versão fixada oferecem a mesma garantia.

A aprovação por chamada muda o equilíbrio. Se uma credencial ou ferramenta exigir confirmação a cada uso, um rebuild ainda precisa criar uma nova identidade para fins de auditoria, mas a ação imediata terá uma nova decisão humana. Isso não elimina a necessidade de atualizar os esquemas. Apenas limita o dano de uma aprovação de sessão desatualizada.

O Sallyport adota uma abordagem relacionada para ações de agentes: seu bloqueio do cofre nega ações enquanto está bloqueado, sua autorização por sessão identifica um processo de agente recém-conectado e configurações individuais de credenciais podem exigir aprovação a cada uso. A lição importante de design é que uma decisão humana precisa de um sujeito claro e de um ponto final, não de uma promessa vaga de que um rótulo familiar continua seguro.

O stdio esconde a substituição de processos atrás de um único pipe

Mantenha os segredos fora do código do agente
O Sallyport executa ações HTTP e SSH sem expor as credenciais do cofre ao agente.

Uma conexão MCP por stdio torna o comportamento de rebuild especialmente enganoso porque a conexão pertence aos processos, não aos arquivos. Recompilar um arquivo não faz nada ao processo filho em execução até que algo substitua ou recarregue esse processo.

No caso simples, um host MCP inicia um servidor filho e mantém seus pipes de entrada e saída padrão. O filho carregou o código ao iniciar. Um desenvolvedor executa o build novamente, mas o filho existente continua na memória. O agente ainda conversa com a implementação antiga, embora o diretório agora contenha novos artefatos.

Nesse caso, nenhuma atualização de protocolo é necessária. A identidade executável real não mudou. O erro está em dizer aos desenvolvedores que o rebuild entrou em vigor quando isso não aconteceu. As ferramentas de desenvolvimento devem imprimir uma linha de status inequívoca, como:

build complete: dist/server.js changed
running server unchanged: pid=48192 epoch=01JQ7R4S4S0QJ7GZP1S2

O caso mais difícil usa um watcher. Um processo pai é dono do pipe stdio, observa os arquivos, encerra o worker e inicia um novo. O pai pode manter o pipe aberto enquanto as chamadas passam silenciosamente a chegar ao novo filho. Do ponto de vista do cliente MCP, a conexão nunca foi encerrada. Do ponto de vista de uma pessoa revisora de segurança, a identidade executável mudou dentro de uma sessão existente.

Não permita que essa troca permaneça invisível. Escolha um destes designs:

  1. Feche a conexão MCP quando o filho reiniciar, obrigando o host a se reconectar, inicializar e autorizar a nova instância.
  2. Mantenha a conexão externa, mas faça o supervisor publicar uma nova época de execução ao host antes de encaminhar qualquer chamada nova.
  3. Evite recargas dentro do processo durante o desenvolvimento e reinicie o processo inteiro do servidor sob o controle do host.

O primeiro design é o mais claro. O segundo pode preservar o contexto de um agente de longa duração, mas exige uma fronteira confiável entre o supervisor e o host. O terceiro custa alguns segundos e evita semanas explicando por que uma aprovação de sessão cobria um código desconhecido.

Não dependa da própria notificação do servidor para atestar sua substituição. O código novo pode mentir, e um servidor comprometido tem todo o interesse em anunciar a mesma identidade. O gerenciador de processos, o host ou o gateway de credenciais deve observar a inicialização e criar a época. Se essas camadas não conseguem observar um reinício, não conseguem distinguir com segurança um rebuild de um servidor estável.

As notificações da lista de ferramentas são uma dica, não uma transferência

notifications/tools/list_changed deve provocar uma nova busca do catálogo, mas não reinicia uma sessão, renegocia capacidades nem transporta uma decisão de autorização. Crie seu fluxo de controle com base no que a notificação realmente diz.

A especificação MCP Lifecycle descreve a inicialização como a fase em que cliente e servidor negociam a versão do protocolo e as capacidades. Depois disso começa a operação normal. Um servidor que anuncia tools.listChanged diz que pode avisar ao cliente que sua lista de ferramentas mudou. Isso não significa que ele possa reescrever sua própria identidade no meio da sessão sem consequências, nem exige que um host trate a notificação como um atestado de segurança.

Essa distinção importa ao projetar um caminho de reload. Uma implementação fraca faz isto:

watcher rebuilds server
server sends tools/list_changed
client fetches tools/list
agent continues

Ela funciona em uma demonstração. Mas não responde a quatro perguntas operacionais:

  • O processo existente carregou o código recompilado?
  • Um processo diferente assumiu a conexão?
  • O novo código tem a mesma autoridade aprovada?
  • O host descartou uma chamada que o agente preparou usando o esquema antigo?

Um caminho mais forte separa as responsabilidades. O sistema de build informa os artefatos. O supervisor informa a substituição do processo. O servidor MCP informa mudanças no catálogo. O host atualiza os metadados visíveis ao agente. A camada de autorização compara a época de execução com a concessão. O log de auditoria registra cada transição.

Se o host receber uma notificação de mudança na lista e depois descobrir uma mudança de época, deve processar primeiro a mudança de época. Marque qualquer catálogo de ferramentas em cache como suspeito, bloqueie chamadas com credenciais até obter o catálogo atual e uma decisão de autorização, e só então retome. O agente pode manter o histórico da conversa. Ele simplesmente não pode presumir que uma invocação de ferramenta composta antes do rebuild continua válida.

A mesma cautela vale para mudanças de capacidades. Se um rebuild adicionar recursos, prompts, comportamento de logging ou uma extensão experimental, uma sessão inicializada anteriormente talvez não tenha negociado esses recursos. Reconecte em vez de tentar alterar a conexão negociada no lugar. Sessões longas são convenientes, mas o contrato de conexão precisa continuar compreensível quando algo der errado às duas da manhã.

Escreva um contrato de atualização antes de adicionar hot reload

Separe as evidências da sessão e da chamada
O Sallyport projeta os diários de sessões e atividades a partir de um único log de auditoria criptografado, encadeado por hashes e sem possibilidade de gravação retroativa.

Um contrato de atualização deve declarar quem detecta um rebuild, qual estado ele altera, quais chamadas são pausadas e quais evidências entram no log de auditoria. Se isso não estiver escrito, cada componente fará uma escolha localmente razoável e o comportamento combinado será inseguro.

Use uma máquina de estados pequena. Ela não precisa de uma linguagem de políticas nem de um labirinto de regras.

ready(epoch A, catalog 12, approval A)
  build artifact changes
ready(epoch A, catalog 12, approval A)
  worker restarts
identity-pending(epoch B, catalog unknown, approval A invalid)
  host fetches tools/list
catalog-ready(epoch B, catalog 13, approval A invalid)
  reviewer approves required scope
ready(epoch B, catalog 13, approval B)

A transição importante é identity-pending. Nesse estado, o host não deve encaminhar uma chamada com credenciais apenas porque o agente já a preparou. Ele pode permitir pedidos de descoberta inofensivos se houver uma definição clara de «inofensivo», mas não faça suposições. Para a maioria dos servidores locais, pausar todas as chamadas de ferramentas até que o catálogo e a concessão estejam atualizados é mais simples.

Seu contrato deve incluir estas decisões em linguagem clara:

  • O componente que cria uma época de execução.
  • Os artefatos e fatos do runtime incluídos na identidade executável.
  • As mudanças de metadados que exigem executar tools/list novamente.
  • Os escopos de autorização que expiram quando a época muda.
  • O comportamento de uma chamada em andamento durante um reinício.

Chamadas em andamento precisam de uma regra firme. Se um worker morrer depois de receber uma chamada de ferramenta, mas antes de produzir uma resposta, devolva um erro que identifique a transição de época. Não repita automaticamente uma escrita contra o novo processo. Uma repetição pode duplicar um pagamento, publicar duas vezes ou aplicar uma mudança depois que os argumentos passaram a ter outro significado.

Para chamadas somente de leitura, uma repetição automática pode ser aceitável se o host conseguir provar que a primeira tentativa nunca chegou ao limite da ação. Essa prova é difícil em subprocessos locais e APIs remotas. Um timeout não é prova. Uma resposta vazia não é prova. Comece com uma falha explícita e adicione novas tentativas seguras apenas quando puder demonstrar idempotência.

Teste rebuilds como mudanças de autoridade

Um teste de rebuild deve provar mais do que «a nova ferramenta aparece». Ele deve provar que metadados antigos não conseguem formar uma chamada perigosa, que uma autorização antiga não chega ao código novo e que a trilha de auditoria distingue as duas épocas de execução.

Execute este teste em um fixture local com um servidor que tenha uma ferramenta de escrita que use credenciais e uma ferramenta de leitura inofensiva.

  1. Inicie a revisão A do servidor. Capture seu registro de execução, busque tools/list e autorize uma execução de agente para a ferramenta de escrita.
  2. Chame a ferramenta de escrita uma vez com um marcador como revision=A. Confirme que o log registra a época A e a concessão de aprovação para a época A.
  3. Recompile a revisão B. Mantenha o mesmo nome de ferramenta, mas adicione um campo obrigatório ao esquema ou altere o handler para escrever revision=B.
  4. Substitua o worker em execução usando o mesmo mecanismo do desenvolvimento normal.
  5. Tente executar a chamada antiga preparada antes de atualizar os metadados e obter aprovação. O host deve negá-la porque a época mudou.
  6. Busque o catálogo novo, obtenha uma nova aprovação se a chamada precisar de autoridade e faça a chamada novamente. Confirme que o log registra a época B e uma nova concessão.

A negação esperada deve ser específica o bastante para permitir a depuração:

{
  "error": "authorization_stale",
  "reason": "server execution epoch changed",
  "approvedEpoch": "01JQ7R4S4S0QJ7GZP1S2",
  "currentEpoch": "01JQ7R9KQ6K2Y8W4JH0M",
  "retry": "refresh tool metadata and request authorization"
}

Não esconda isso atrás de uma mensagem genérica como «ferramenta indisponível». O agente precisa saber se deve atualizar o catálogo, esperar um reinício do servidor ou pedir ajuda a uma pessoa. A pessoa operadora precisa saber se um watcher substituiu um worker inesperadamente.

Adicione testes de falha que desenvolvedores costumam ignorar:

  • O build tem sucesso, mas o processo antigo continua em execução.
  • O processo reinicia, mas a lista de ferramentas permanece idêntica.
  • O esquema muda, mas um cliente ignora tools/list_changed.
  • Ocorre um reinício enquanto uma chamada de escrita aguarda uma resposta.
  • O caminho do servidor permanece fixo enquanto a árvore de dependências resolvida muda.

Esses testes mostram se o design depende de um servidor amigável dizendo a verdade. Não deveria depender. O código de desenvolvimento local é justamente onde a ampliação acidental de confiança acontece, porque os desenvolvedores recompilam o tempo todo e as suposições ficam invisíveis.

Os registros de auditoria precisam responder qual código agiu

Rastreie cada chamada externa
O diário de atividades registra cada ação individual no log de auditoria criptografado.

Um registro de auditoria deve permitir determinar qual época executável tratou uma chamada, ou não conseguirá resolver um incidente envolvendo um rebuild. Nome da ferramenta, argumentos e horário são úteis, mas deixam sem resposta a pergunta mais difícil.

Registre a época de execução em cada chamada de ferramenta. Registre a revisão do catálogo ou o digest dos metadados quando o host apresentar informações da ferramenta ao agente. Registre as decisões de aprovação com o sujeito coberto por elas. Se uma chamada atravessar uma fronteira de credenciais, registre o nome do escopo da credencial, sem registrar o segredo.

Uma sequência compacta de eventos pode ser assim:

{"type":"server_started","epoch":"01JQ7R4...","entryDigest":"sha256:9e4c...71af"}
{"type":"approval_granted","run":"run_01JQ7R1","epoch":"01JQ7R4...","scope":"inventory-api-staging"}
{"type":"tool_called","run":"run_01JQ7R1","epoch":"01JQ7R4...","tool":"inventory_adjust"}
{"type":"server_replaced","oldEpoch":"01JQ7R4...","newEpoch":"01JQ7R9..."}
{"type":"authorization_denied","run":"run_01JQ7R1","epoch":"01JQ7R9...","reason":"stale_epoch"}

Essa estrutura também ajuda na depuração comum. Quando alguém relatar que um agente usou um esquema antigo depois de um rebuild, você poderá ver se o host não atualizou os metadados, se o servidor nunca reiniciou ou se um supervisor mudou o código sem avisar. São defeitos diferentes e não devem acabar na mesma categoria de bug.

O diário de sessões e o diário de atividades do Sallyport são bons exemplos da separação entre registros da execução do agente e registros de ações individuais, projetando ambos a partir de um único log de auditoria criptografado e encadeado por hashes. A mesma separação se aplica aqui: um registro explica quem foi autorizado a executar, e outro explica qual chamada ocorreu sob qual época de execução.

Não faça o sistema de auditoria depender do servidor para declarar sua própria identidade. Capture a identidade junto à inicialização do processo ou ao despacho de credenciais. Depois, verifique a cadeia de auditoria de forma independente quando o ambiente permitir. Um servidor que pode alterar o código durante uma sessão não pode ser a única testemunha de qual código foi executado.

A velocidade do rebuild não justifica confiança herdada

Rebuilds rápidos são uma conveniência de desenvolvimento. Eles não transformam código novo em código previamente revisado. Se um servidor MCP local pode acessar credenciais, arquivos ou sistemas remotos, um rebuild deve criar uma fronteira visível entre o código aprovado e o código que agirá em seguida.

Comece tornando observável a substituição do processo. Adicione uma época na inicialização. Vincule a autorização da sessão a essa época. Atualize os metadados das ferramentas sempre que o contrato mudar. Depois faça um teste falhar de propósito: recompile um servidor durante uma sessão ativa do agente e confirme que a próxima chamada com credenciais é interrompida até que o host tenha metadados atuais e uma concessão atualizada.

Se esse teste passar pelo motivo correto, seu agente poderá continuar trabalhando depois de um rebuild sem receber uma permissão que pertence a um executável anterior.

FAQ

É preciso reiniciar o agente depois de recompilar um servidor MCP?

Um rebuild, por si só, nem sempre exige um reset. Se o processo em execução ainda mantiver o código antigo na memória, nada mudou de fato. Redefina a sessão quando uma nova instância executável puder receber chamadas, especialmente se o código recompilado puder alterar o comportamento de uma ferramenta existente.

O que `tools/list_changed` faz depois de recompilar um servidor MCP?

Use notifications/tools/list_changed quando a lista de ferramentas, suas descrições ou seus esquemas mudarem. Trate-o como um pedido para que o cliente busque metadados atualizados, não como uma prova de que todos os clientes farão isso imediatamente. A notificação não estabelece uma nova identidade executável nem renova a autorização.

Um servidor MCP local recompilado precisa de aprovação novamente?

Um novo processo de servidor precisa de uma nova aprovação quando a autorização está vinculada à instância executável, ao digest do build ou ao contexto de inicialização. Esse é o padrão seguro para servidores locais de desenvolvimento com acesso a credenciais, arquivos ou APIs de produção. Reutilizar a aprovação depois que um código desconhecido substitui o anterior transforma um clique em permissão para um código que a pessoa revisora nunca viu.

O caminho do executável basta para identificar um servidor MCP?

Não. Um caminho informa onde o launcher procurou, não quais bytes o sistema operacional executou. Use uma identidade de execução que inclua o digest do artefato de inicialização, o runtime ou interpretador usado, o estado relevante das dependências e uma nova época do processo ou do servidor.

O que fazer quando muda apenas o esquema de entrada de uma ferramenta MCP?

Uma alteração no esquema de uma ferramenta pode fazer um argumento antes seguro adquirir outro significado. Por isso, atualize os metadados sempre que o esquema mudar. Se a implementação em execução também mudou, substitua a identidade e invalide as autorizações vinculadas a ela. São ações separadas porque metadados e bytes executáveis respondem a perguntas diferentes.

É possível fazer hot reload de um servidor MCP com segurança?

O hot reload só é seguro quando o mecanismo de recarga publica uma nova época de execução e a camada de autorização consegue observá-la. Uma recarga que substitui handlers silenciosamente dentro de um processo de longa duração é difícil de revisar e ainda mais difícil de auditar. No desenvolvimento local, reiniciar completamente o processo filho costuma ser mais fácil de entender.

O MCP renegocia capacidades depois que um servidor é recompilado?

A especificação MCP Lifecycle trata a inicialização como a negociação de capacidades de uma conexão, não como um protocolo geral de rebuild. As notificações sobre mudanças na lista de ferramentas ajudam na descoberta, mas não renegociam a conexão nem atestam a existência de um novo código de servidor. O host ou gateway precisa de um contrato próprio para atualizar identidade e aprovações.

Posso manter o mesmo nome de ferramenta MCP depois de mudar seu comportamento?

Mantenha o mesmo nome somente se a autoridade e o significado dos argumentos permanecerem estáveis. Se deploy mudar de uma simulação para uma implantação real, use um novo nome ou imponha uma fronteira clara de nova autorização. Nomes estáveis são convenientes para prompts, mas conveniência não é uma propriedade de segurança.

O que um log de auditoria deve registrar para servidores MCP recompilados?

Registre o identificador da execução do agente, o identificador do processo do servidor, o digest do executável, a época do servidor, o digest dos metadados da ferramenta, a decisão de aprovação e cada chamada. Assim, você consegue saber se uma chamada ocorreu antes ou depois do rebuild. Um diário que registra apenas nomes de ferramentas não consegue responder a essa pergunta.

Como um gateway MCP deve lidar com um servidor recompilado?

Um gateway deve autorizar a ação com base na identidade atual do servidor, não apenas no rótulo fornecido pelo agente. Ele deve negar chamadas quando a identidade mudar depois da aprovação e registrar essa decisão. As credenciais devem permanecer fora do agente e do processo do servidor local, a menos que esse processo tenha sido explicitamente confiado para armazená-las.

Sallyport

O Sallyport executa chamadas de API e comandos SSH pelo seu agente de IA. As chaves ficam em um cofre local no seu Mac; você aprova cada execução e toda ação vai para um registro selado.

© 2026 Sallyport · Código aberto sob Apache-2.0 · Oleg Sotnikov