8 min de leitura

Como a deriva de esquema do MCP quebra agentes de longa duração

A deriva de esquema do MCP pode quebrar agentes de longa duração depois que um servidor altera suas ferramentas. Teste esquemas obsoletos, migrações seguras, novas tentativas, resultados e aprovações.

Como a deriva de esquema do MCP quebra agentes de longa duração

Agentes de longa duração tornam uma suposição errada muito cara: a de que a descrição da ferramenta carregada no início da sessão continuará válida até o fim da execução. Muitas vezes, isso não acontece. Um servidor pode publicar uma nova versão, ativar uma capacidade específica de uma conta, trocar uma API upstream ou corrigir o contrato de um resultado enquanto o agente ainda planeja com base no formato de ferramenta de ontem.

Isso é deriva de esquema no MCP. Não é um caso exótico do protocolo. É uma alteração de contrato entre um cliente que já formou um plano e um servidor que seguiu adiante. Se você testa apenas uma conexão nova depois de uma implantação, está testando o caso fácil e deixando o perigoso de lado.

O Model Context Protocol oferece aos servidores uma forma de anunciar alterações na lista de ferramentas. Ele não transforma o cache antigo de um cliente em um contrato novo, não corrige chamadas de ferramentas que o modelo já propôs nem decide se uma solicitação antiga continua segura. Essas são decisões de engenharia. Tome-as de forma deliberada e teste-as enquanto a sessão estiver ativa.

A descrição de uma ferramenta faz parte do estado da sessão

Um esquema de ferramenta é contexto executável. O agente usa o nome, a descrição, o esquema de entrada, as anotações e, às vezes, o esquema de saída para decidir qual ação solicitar. Muitos clientes também convertem tools/list em estruturas locais, compilam validadores ou colocam uma descrição compacta da ferramenta no contexto do modelo. Nenhuma dessas cópias muda só porque o servidor publicou outra versão.

Isso importa mesmo quando o protocolo de comunicação está funcionando exatamente como previsto. Suponha que um cliente tenha começado com esta ferramenta:

{
  "name": "deploy_preview",
  "description": "Deploy the current branch to a preview environment.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "branch": { "type": "string" }
    },
    "required": ["branch"],
    "additionalProperties": false
  }
}

Uma hora depois, o servidor altera a operação e passa a exigir um campo region explícito. Um cliente conectado depois da alteração vê o novo esquema e pode fornecê-lo. O cliente antigo ainda acredita que {"branch":"fix-login"} é uma solicitação completa.

Aqui existem três estados distintos, que as equipes costumam misturar:

  1. O esquema anunciado é o que o servidor retorna agora em tools/list.
  2. O snapshot do esquema no cliente é o que um cliente específico guardou na última vez em que listou as ferramentas.
  3. O contrato de execução é o que o servidor aceitará e fará quando receber tools/call.

O servidor pode atualizar o primeiro estado imediatamente. Não pode presumir que o segundo também foi atualizado. Precisa escolher como tratar o terceiro.

Chamar isso apenas de um problema de invalidação de cache é incompleto. Invalidação de cache parece um problema de dados de exibição desatualizados. Um esquema de ferramenta pode definir contas de destino, escopo de escrita, campos de confirmação e o significado dos resultados. Quando um agente mantém a versão antiga, a divergência pode gerar trabalho malsucedido, novas tentativas repetidas ou uma solicitação que agora significa mais do que o modelo pretendia.

O padrão mais seguro é simples: mantenha o contrato de entrada aceito por uma ferramenta publicada compatível com versões anteriores durante uma janela de transição, a menos que aceitar a entrada antiga torne a ação insegura. Quando segurança e compatibilidade entrarem em conflito, rejeite claramente o formato antigo e exija uma nova decisão.

tools/list_changed anuncia a alteração, mas não a sincroniza

A especificação do MCP define notifications/tools/list_changed para servidores cuja lista de ferramentas muda. O servidor envia uma notificação, e o cliente pode atualizar suas ferramentas com tools/list. A especificação também prevê o suporte a notificações de alteração da lista na capacidade de ferramentas do servidor, negociada durante a inicialização.

Isso é útil, mas a palavra «pode» faz bastante trabalho. Uma notificação não tem resposta. Apenas com a notificação, o servidor não consegue saber se o cliente a recebeu, se atualizou a lista, se o cache foi atualizado ou se o modelo já redigiu uma chamada usando a descrição anterior.

Trate a notificação como um sinal de invalidação, não como uma barreira de sincronização.

Um cliente que lida bem com a deriva deve fazer quatro coisas depois de receber a notificação:

  • Solicitar tools/list novamente e substituir atomicamente as definições locais correspondentes.
  • Preservar o snapshot antigo por tempo suficiente para associar uma chamada já planejada ao esquema que a produziu.
  • Validar novamente qualquer chamada enfileirada contra o esquema atualizado antes de enviá-la.
  • Fornecer ao modelo um erro reparável quando uma chamada criada com contexto antigo não puder mais ser executada.

É no terceiro item que os clientes costumam cortar caminho. Eles atualizam a lista de ferramentas visível, mas permitem que uma chamada já enfileirada saia com o objeto de argumentos antigo. Isso cria uma condição de corrida: a interface diz uma coisa, o agente envia outra e o servidor precisa limpar a divergência.

Os servidores precisam de uma disciplina paralela. Quando uma ferramenta mudar, envie a notificação depois que a nova resposta de tools/list estiver pronta. Não anuncie um contrato novo e depois deixe um processo antigo tratar chamadas durante um intervalo arbitrário. Se sua topologia de implantação permitir isso, inclua uma revisão explícita do contrato na resposta do servidor e rejeite chamadas que cheguem a um worker com comportamento incompatível.

A notificação também não resolve o caso de clientes que não a suportam, que se desconectam durante o evento ou que passam por um intermediário com seu próprio cache. A compatibilidade em tools/call continua necessária. Se o servidor só funciona quando todos os clientes respondem perfeitamente a uma notificação, ele não funciona em produção.

Alterações de entrada carregam tipos diferentes de quebra

Adicionar um campo não é uma única categoria de alteração. O risco depende de o campo mudar a validação, o significado ou a autoridade.

Adicionar uma preferência opcional de exibição costuma ser seguro. O chamador antigo a omite, e o servidor escolhe um valor padrão estável. Um filtro opcional também pode ser seguro se omiti-lo produzir o mesmo resultado de antes.

Adicionar uma region obrigatória a deploy_preview é diferente. O chamador antigo deixa de satisfazer o validador. Você pode rejeitar a solicitação ou fornecer um valor padrão. A primeira opção interrompe o agente, mas declara a verdade. A segunda só é aceitável se o valor padrão sempre tiver sido a região pretendida para aquele repositório e não puder redirecionar uma implantação para um ambiente mais sensível.

Alterar o significado de um campo é pior do que adicionar um campo obrigatório. Considere uma ferramenta que originalmente aceita project como um identificador legível de projeto. Depois, o servidor decide que project deve ser um identificador opaco de organização. Um agente antigo ainda pode enviar payments, e o servidor pode resolver essa string em um namespace inesperado. A validação passa, a solicitação é concluída e a ação está errada. Essa é uma quebra semântica, mais perigosa do que um erro de validação claro.

Remover um campo de entrada exige o mesmo cuidado. additionalProperties: false no JSON Schema torna a quebra visível. Um cliente antigo envia um argumento antes válido e recebe uma falha. Se o servidor ignorar silenciosamente o campo removido, a chamada pode ser concluída com uma interpretação diferente da esperada pelo modelo.

O conselho popular de «ser liberal no que você aceita» é ruim para ferramentas de ação. Ele se popularizou porque mantém integrações funcionando diante de alterações descuidadas. Para uma preferência de formatação somente de leitura, essa tolerância pode ser inofensiva. Para uma solicitação HTTP com credenciais, um comando SSH, uma implantação, uma exclusão ou um pagamento, a interpretação permissiva transforma uma solicitação ambígua em uma tentativa de adivinhação no servidor.

Use um adaptador de compatibilidade apenas quando puder descrever seu comportamento com precisão. Por exemplo:

function normalizeDeployArgs(raw: unknown) {
  if (!isPlainObject(raw)) {
    throw executionError("Expected an object for deploy_preview.");
  }

  if (typeof raw.branch !== "string" || raw.branch.length === 0) {
    throw executionError("The branch field must be a non-empty string.");
  }

  if (raw.region === undefined) {
    return { branch: raw.branch, region: "us-east-preview", schemaRevision: 1 };
  }

  if (raw.region !== "us-east-preview" && raw.region !== "eu-preview") {
    throw executionError("region must be us-east-preview or eu-preview.");
  }

  return { branch: raw.branch, region: raw.region, schemaRevision: 2 };
}

Esse adaptador tem uma propriedade aceitável: a solicitação antiga produz o mesmo destino de preview que produzia antes. Ele não seria aceitável se us-east-preview fosse apenas um palpite conveniente depois de uma alteração na propriedade da conta.

Para uma alteração incompatível, rejeite com um erro que o agente possa usar. Diga qual revisão da ferramenta o servidor espera, informe o campo ausente ou obsoleto e peça ao cliente para atualizar suas ferramentas. Não retorne uma mensagem vaga como «entrada inválida». Os modelos repetem erros vagos com pequenas variações. Erros claros criam uma chance de reparo.

Alterações no formato do resultado podem envenenar a próxima decisão

As equipes prestam atenção à validação de entrada porque uma solicitação inválida para no servidor. Elas examinam menos as alterações dos resultados porque a ação já foi concluída. Para agentes, isso é o inverso do que deveriam fazer. O resultado costuma fornecer a evidência que orienta a próxima chamada.

Imagine um resultado original de create_issue:

{
  "issue": {
    "id": "I-482",
    "url": "https://tracker.example/issues/I-482",
    "state": "open"
  }
}

Um agente pode extrair issue.id, guardá-lo na memória de trabalho e depois chamar add_comment com esse identificador. Se um servidor revisado renomear id para issueId, envolver o resultado em data ou mudar state de uma string para um objeto, a próxima ação do agente pode falhar muito longe da chamada original. Pior ainda, um fallback apenas textual pode continuar contendo uma frase plausível, e o modelo pode improvisar um identificador a partir da prosa.

Os resultados das ferramentas MCP podem incluir conteúdo para o modelo e conteúdo estruturado para uso programático. Se você publicar um esquema de saída, faça da saída estruturada o contrato oficial para máquinas. Mantenha o texto conciso e útil para uma pessoa lendo a transcrição, mas não espere que os clientes consigam extraí-lo de forma confiável.

O trabalho do MCP com JSON Schema 2020-12 é relevante aqui. As orientações posteriores do protocolo tornam o dialeto explícito, e os esquemas de saída podem descrever mais do que um subconjunto de JSON em formato de objeto. Isso melhora a expressividade, mas não dá licença para remodelar casualmente um resultado em produção. Um cliente pode validar resultados com um draft específico, um tipo gerado ou um decodificador sem tolerância à sua nova forma de união ou array.

Para a evolução dos resultados, siga estas regras:

  1. Adicione campos antes de renomeá-los ou removê-los.
  2. Mantenha estáveis os significados dos campos, especialmente identificadores, valores de status e timestamps.
  3. Inclua um campo schema_revision ou result_version na saída estruturada quando várias interpretações precisarem coexistir.
  4. Retorne um objeto de erro estruturado completo quando a execução falhar, em vez de transformar um resultado de sucesso em um pedido de desculpas não estruturado.
  5. Remova o formato antigo apenas depois de encerrar as sessões antigas ou concluir uma janela de migração publicada.

Um campo de revisão do resultado não é enfeite. Ele permite que o cliente diferencie «o servidor retornou uma resposta antiga incompleta» de «o servidor retornou uma resposta nova cujo campo opcional está ausente». Essa diferença importa quando um agente decide se deve tentar novamente, perguntar ao usuário ou prosseguir para uma ação consequente.

Não transforme toda saída em um envelope versionado só porque isso é possível. Coloque um marcador de revisão onde vários consumidores implantados de forma independente precisarem dele. Para um servidor privado pequeno e um único cliente integrado, um formato estável e aditivo pode bastar. Para uma ferramenta compartilhada por vários hosts de agentes, workers e plugins, informações explícitas de revisão economizam dias de suposições durante um incidente.

O caso que vale testar é um plano antigo contra um servidor novo

Revogue uma execução de agente desatualizada
O diário Sessions mostra as execuções dos agentes e permite revogar uma execução imediatamente.

Um cliente novo contra um servidor novo mostra que o esquema novo é válido. Não diz nada sobre deriva. O teste necessário faz um cliente guardar um snapshot, permite que o servidor mude e depois executa chamadas originadas desse snapshot.

Monte o teste com dois fixtures de servidor. O fixture A anuncia a definição antiga da ferramenta. O fixture B anuncia a definição nova e controla como trata os argumentos antigos. O cliente permanece conectado durante a transição. Se o servidor não puder mudar de comportamento sem reiniciar, coloque uma chave de teste determinística atrás do registro de ferramentas, em vez de tentar reproduzir o momento exato com o sistema de implantação.

Esta é a transcrição mínima útil:

1. Client initializes and receives tools.listChanged capability.
2. Client calls tools/list and stores deploy_preview revision 1.
3. Client prepares arguments: {"branch":"fix-login"}.
4. Server switches to revision 2, where region is required for new clients.
5. Server emits notifications/tools/list_changed.
6. Client sends the already prepared revision 1 call.
7. Client refreshes tools/list.
8. Client retries only if its repair policy permits it.
9. Client calls revision 2 with {"branch":"fix-login","region":"us-east-preview"}.

O teste deve examinar mais do que sucesso ou falha. Capture as mensagens JSON-RPC reais, os argumentos normalizados pelo servidor, as chamadas aos serviços externos simulados e o registro de eventos do cliente. Um servidor que retorna um erro organizado, mas já iniciou uma implantação externa, falhou no teste.

Use um serviço downstream falso com um registro de solicitações somente de acréscimo. Ele deve registrar o método, o caminho, os cabeçalhos relevantes para autorização, o corpo da solicitação e um ID de correlação de teste. Depois, confirme que a chamada obsoleta não fez nenhuma solicitação downstream quando deveria ter falhado de forma segura.

Uma tabela compacta torna o comportamento esperado fácil de revisar:

Evento de derivaComportamento do cliente antigoComportamento do servidorEfeito downstream
Adição de label opcionalChama sem labelAplica o valor padrão anteriorUma solicitação esperada
Adição de region obrigatória com valor padrão histórico seguroChama sem regionNormaliza para o valor padrão estávelUma solicitação esperada
Adição de escopo de aprovação obrigatórioChama sem o escopoRetorna um erro de execução reparávelNenhuma solicitação
Alteração do significado de projectChama com o project antigoRejeita como incompatívelNenhuma solicitação
Adição de campo ao resultadoAnalisa os campos anterioresRetorna os campos antigos e o novoNenhuma ação extra
Remoção do identificador do resultadoTenta a próxima chamada dependenteO cliente para e informa um erro de contratoNenhuma solicitação dependente

Não teste apenas a nova tentativa bem-sucedida. Agentes são bons em repetir chamadas, e é justamente por isso que podem ampliar uma migração ruim. Teste chamadas obsoletas repetidas, uma notificação que chega depois que a chamada entrou na fila, uma atualização que falha e um cliente que se reconecta no meio da transição.

O caso mais incômodo é uma chamada de ferramenta em andamento. O servidor deve executar cada chamada com base em uma única revisão de contrato coerente. Não comece a validação na revisão 1, recarregue a configuração e depois monte a solicitação downstream na revisão 2. Faça um snapshot da configuração do handler quando a chamada for admitida. Se a operação puder durar o suficiente para que o próprio contrato de destino mude, exponha um trabalho durável ou rejeite a chamada antes da fase irreversível. Não misture duas revisões em uma ação.

A lógica de reparo do cliente precisa de um limite para novas tentativas

Quando um servidor rejeita uma solicitação obsoleta, o cliente tem várias opções: atualizar, pedir ao modelo para corrigir os argumentos, repetir com uma solicitação mapeada ou parar e pedir dados ao usuário. A escolha correta depende de a alteração afetar apenas a sintaxe ou a autoridade da ação.

Atualize automaticamente e tente novamente apenas quando todas estas condições forem verdadeiras:

  • O servidor identifica explicitamente uma revisão de esquema obsoleta ou um campo ausente.
  • A definição atualizada da ferramenta fornece um valor padrão inequívoco e não sensível ou um mapeamento determinístico.
  • A ação original continua dentro do mesmo limite de destino e permissões.
  • A primeira tentativa não produziu nenhum efeito externo.

Qualquer outro caso exige uma nova decisão. Se uma revisão acrescentar environment, account_id, repository, host, user ou um texto de confirmação, uma nova tentativa automática pode ampliar ou redirecionar a ação. Mesmo que o modelo consiga inferir uma resposta provável, ele deve obter contexto atualizado ou aprovação humana.

Mantenha a identidade da solicitação separada da identidade da nova tentativa. Se uma chamada de ferramenta puder chegar a um sistema externo antes que o cliente receba sua resposta, o cliente não deve reenviá-la cegamente depois de atualizar o esquema. Use um token de idempotência quando a API downstream oferecer suporte. No SSH, onde não há um mecanismo genérico de idempotência, projete os comandos para que uma execução repetida seja segura ou detectável. Uma migração de esquema é um péssimo momento para descobrir que um timeout gera trabalho duplicado.

Um bom erro do cliente fornece informações ao modelo sem entregar uma instrução falsa. Por exemplo:

{
  "isError": true,
  "content": [
    {
      "type": "text",
      "text": "deploy_preview rejected this request because its input contract changed. Refresh tools before retrying. The current schema requires branch and region. No deployment was started."
    }
  ],
  "structuredContent": {
    "error_code": "STALE_TOOL_SCHEMA",
    "tool": "deploy_preview",
    "required_action": "refresh_tools",
    "side_effect_started": false,
    "current_revision": 2
  }
}

O envelope exato do erro é uma decisão sua, mas os fatos não são opcionais. Informe se algum efeito começou. Informe se uma atualização pode ajudar. Informe a revisão atual, caso o servidor exponha revisões. Um modelo pode usar esses fatos. Um erro de transporte genérico não pode.

Não rotule um problema de validação de esquema como falha de transporte. A especificação MCP distingue falhas no nível do protocolo de falhas na execução da ferramenta, e as orientações atuais favorecem erros de execução da ferramenta para entradas inválidas, dando ao modelo uma chance de se corrigir. Use essa distinção. Um método JSON-RPC desconhecido não é o mesmo evento que uma ferramenta conhecida rejeitando argumentos obsoletos.

A revisão de segurança precisa cobrir o significado, não apenas os segredos

Mantenha as credenciais fora dos ciclos de reparo
O Sallyport executa ações HTTP e SSH sem colocar as credenciais no contexto de ferramentas do agente.

A deriva de esquema se torna um problema de segurança quando uma descrição antiga autoriza implicitamente uma ação nova. Isso acontece por meio de valores padrão, campos renomeados, escopos adicionados e adaptadores de servidor prestativos demais.

Considere uma ferramenta originalmente chamada run_report com {\"team\":\"sales\"}. O servidor muda para aceitar uma string target que pode indicar uma equipe, um relatório salvo ou uma consulta bruta. Um agente antigo ainda envia team. Se o adaptador transformar isso em target: \"sales\", o que foi autorizado? Uma equipe? Um relatório chamado sales? Um alias de consulta? O servidor criou ambiguidade no limite de uma ação. Rejeite a solicitação e publique uma ferramenta distinta ou um caminho de migração explícito.

As credenciais aumentam o risco. Um agente que mantém chaves de API diretamente pode misturar o reparo do esquema com o tratamento dos segredos em seu próprio processo e nos próprios logs. Isso dá a um plano obsoleto mais espaço para causar danos. O Sallyport mantém credenciais HTTP e SSH em seu cofre criptografado e executa a ação sem entregar a credencial ao agente. Essa separação não torna um contrato de ferramenta alterado seguro por si só, mas facilita a inspeção da solicitação real, do ponto de autorização e do registro de auditoria.

A aprovação deve estar vinculada à ação concreta que acontecerá agora, não a uma descrição de ferramenta lembrada. Se uma ferramenta mudar de um host para um seletor flexível de hosts, uma aprovação por sessão baseada em uma identidade de código anterior não basta para o novo destino. Exija uma aprovação nova por chamada para a ação sensível ou use um novo nome de ferramenta que torne visível o aumento de autoridade.

É também aqui que os registros de auditoria mostram seu valor. Registre o nome da ferramenta, a revisão declarada do esquema quando disponível, os argumentos brutos recebidos, os argumentos normalizados usados, a versão do servidor ou do handler, a decisão de aprovação e o destino downstream. Não substitua os argumentos brutos pelos normalizados. Durante um incidente, você precisa saber se o cliente enviou um formato antigo, se o adaptador o alterou e se a solicitação externa correspondeu ao que o adaptador prometia.

O diário Activity e o diário Sessions do Sallyport são bons exemplos de como separar uma execução de agente de chamadas externas individuais. Para testes de deriva, você quer as duas visões: um registro de que a execução foi autorizada e outro registro para cada ação HTTP ou SSH que saiu ou não da máquina.

Use janelas de compatibilidade e encerre-as de propósito

Inspecione cada chamada externa
O diário Activity registra chamadas HTTP e SSH individuais depois que um agente as envia.

A compatibilidade com versões anteriores deve ter uma data de término, mesmo que essa data esteja ligada a um ciclo de lançamento ou à duração de uma sessão, e não ao calendário. Caso contrário, todo mapeador de entrada obsoleto permanece para sempre, e o servidor vira um museu de suposições que ninguém consegue editar com segurança.

Comece classificando a alteração.

Uma alteração aditiva mantém a chamada antiga válida e preserva seu significado. Mantenha o mesmo nome da ferramenta, anuncie a alteração da lista e aceite os dois formatos enquanto as sessões ativas terminam.

Uma migração restrita muda a sintaxe, mas permite um mapeamento determinístico seguro. Mantenha o nome da ferramenta apenas se puder testar o mapeador de forma exaustiva e registrar quando ele for usado. Informe aos clientes novos o esquema atual e aceite a entrada antiga somente durante uma janela curta.

Uma alteração semântica ou de autoridade exige um novo nome de ferramenta. deploy_preview e deploy_environment podem compartilhar a implementação, mas não devem compartilhar um contrato se uma seleciona um destino de preview conhecido e a outra pode selecionar produção. Isso pode parecer excesso de nomes na lista de ferramentas. Ainda assim, custa menos do que fazer um agente acreditar que chamou a operação mais restrita.

Uma remoção deve falhar claramente. Retorne um erro de execução que indique a ferramenta substituta ou diga que a capacidade desapareceu. Não mantenha um nome de ferramenta que não faz nada. O sucesso silencioso é veneno para o trabalho automatizado, porque o agente registra a conclusão enquanto o efeito pretendido nunca aconteceu.

Use telemetria para decidir quando remover um adaptador, mas não colete apenas contagens agregadas de sucesso. Conte as chamadas normalizadas a partir de cada revisão antiga, as chamadas obsoletas rejeitadas, os reparos automáticos dos clientes e as chamadas que exigiram intervenção humana. Um volume baixo de entradas antigas ainda pode importar se elas vierem dos trabalhos de agentes mais longos ou com mais privilégios.

Antes da remoção, execute o teste de deriva ao contrário: inicie um cliente na versão antiga, atualize o servidor além da janela de compatibilidade e confirme que a falha é clara, não produz efeitos colaterais e pode ser recuperada por uma reconexão ou atualização das ferramentas. Uma ruptura limpa é melhor do que uma reinterpretação silenciosa.

Um bloqueio de lançamento que detecta a deriva antes dos usuários

Inclua a deriva de esquema no bloqueio de lançamento de todo servidor MCP capaz de executar ações. Não é necessário criar uma matriz enorme no primeiro dia. É preciso ter um fixture disciplinado para cada classe de alteração de contrato.

Para cada ferramenta alterada, responda a estas perguntas na solicitação de pull ou na revisão do lançamento:

  1. Uma sessão existente ainda pode enviar os argumentos válidos anteriores?
  2. Se sim, esses argumentos mantêm exatamente o significado da ação anterior?
  3. Se não, a rejeição ocorre antes de qualquer efeito externo?
  4. O servidor emite notifications/tools/list_changed somente depois que a lista substituta está disponível?
  5. O cliente consegue explicar o caminho de reparo sem inventar uma autoridade ausente?

Depois, transforme as respostas em testes. Armazene os fixtures de tools/list antigo e novo ao lado do teste. Execute a sequência com um snapshot antigo do cliente. Valide as solicitações downstream, não apenas as respostas do MCP. Mantenha um fixture de regressão depois que a migração for publicada, porque a próxima refatoração pode remover um ramo de compatibilidade sem que ninguém se lembre do motivo de sua existência.

O primeiro teste que vale adicionar é brutalmente pequeno: liste uma ferramenta, altere um parâmetro obrigatório, faça a chamada antiga e prove que o servidor preserva o comportamento seguro anterior ou não faz nada. Esse teste força a pergunta que a maioria das implantações evita: o que exatamente um agente já em execução tem permissão para significar depois que você altera a ferramenta sob ele?

FAQ

O que é deriva de esquema no MCP?

Um cliente MCP de longa duração pode manter as definições das ferramentas na memória muito depois de o servidor alterá-las. A próxima chamada pode falhar na validação, ser interpretada segundo um contrato diferente ou produzir uma saída que o cliente interpreta de forma incorreta. Trate o esquema como uma dependência da sessão, não como uma decoração da inicialização.

Um servidor MCP pode alterar suas ferramentas enquanto uma sessão está em execução?

Sim. O MCP fornece notifications/tools/list_changed para que um servidor informe ao cliente que suas ferramentas oferecidas foram alteradas. Essa notificação é um aviso para atualizar com tools/list; ela não atualiza automaticamente todas as cópias armazenadas no cliente ou no contexto do modelo.

Adicionar um parâmetro obrigatório a uma ferramenta MCP é uma alteração incompatível?

Adicionar uma entrada opcional costuma ser a alteração menos perigosa, desde que os valores padrão antigos mantenham o mesmo significado. Adicionar um campo obrigatório quebra clientes antigos que chamam a ferramenta com o formato de argumentos armazenado em cache. Se o novo campo alterar a autorização ou a seleção do destino, não o esconda atrás de um valor padrão.

`tools/list_changed` garante que os clientes atualizem seus esquemas?

Não. Um cliente pode ignorar a notificação, adiar a atualização ou manter uma representação antiga da ferramenta no contexto atual do modelo. Para ferramentas importantes, crie janelas de compatibilidade e teste deliberadamente o caminho com um esquema obsoleto.

Como alterar o resultado de uma ferramenta MCP sem quebrar os agentes?

Mantenha o nome da ferramenta e os campos antigos do resultado estáveis durante um período de transição definido. Adicione campos em vez de renomear os antigos e inclua uma revisão do esquema na saída estruturada quando os consumidores precisarem escolher entre comportamentos. Remover um campo ou alterar seu significado exige uma transição coordenada.

Como testar um cliente com um esquema antigo de ferramenta MCP?

O teste mais forte inicia uma sessão real do cliente, registra a resposta original de tools/list, altera o servidor e depois faz chamadas usando o esquema antigo, antes e depois da atualização. Verifique o resultado JSON-RPC, o resultado estruturado, o conteúdo legível, o número de tentativas e qualquer efeito externo.

O que um servidor MCP deve fazer ao receber argumentos obsoletos?

Não reinterprete silenciosamente um argumento antigo como autorização para uma ação mais ampla. Retorne um erro de execução claro, inclua o campo esperado atualmente ou o caminho de migração e exija que o agente atualize as ferramentas ou peça aprovação. Uma solicitação antiga inválida deve falhar de forma segura antes de chegar a um sistema externo.

Por que a deriva de esquema é um problema de segurança para agentes de IA?

A deriva de esquema pode transformar uma ação aparentemente inofensiva em uma solicitação externa diferente quando nomes, valores padrão ou significados dos resultados mudam. Ela também confunde a auditoria, porque o cliente pode descrever uma operação enquanto o servidor executa outra. A aprovação humana só ajuda quando quem aprova vê a ação, o destino e o uso das credenciais reais.

Quando devo criar um novo nome de ferramenta MCP em vez de alterar uma ferramenta existente?

Use um nome de ferramenta com versão quando o significado, a autoridade ou a confirmação exigida pela operação mudar. Use uma atualização aditiva no mesmo lugar quando a chamada antiga continuar segura e semanticamente correta. O versionamento exige mais contexto e trabalho de migração, mas custa menos do que tentar adivinhar o significado de uma solicitação antiga.

Como é um teste de deriva de esquema que passou?

Passar significa mais do que receber uma resposta depois da atualização. O cliente precisa evitar novas tentativas malformadas, preservar o limite correto da ação, mostrar ao modelo uma mensagem útil para o reparo e manter um registro completo do esquema e dos argumentos que o servidor realmente aceitou.

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