Voltar as noticias
Desenvolvimento de um servidor MCP para assistentes de IA
MCP ProtocolAltaEN

Desenvolvimento de um servidor MCP para assistentes de IA

Dev.to - MCP·15 de agosto de 2026

Eu construí um servidor MCP que permite que um assistente de IA troque tokens e reivindique taxas de criador em
Solana. Então, enviei uma versão onde as duas ferramentas de escrita construíram transações, descartaram
-nas e retornaram sucesso. Nada foi assinado. Nada foi submetido.

Ele tinha 337 testes. Todos passaram.

Eu não descobri isso por três meses.

Este post é sobre o que esse bug me ensinou e o design que ele produziu — porque a
parte interessante não é o bug, é que cada bloqueio que eu tinha em vigor estava verde enquanto a
única coisa que o produto existia para fazer não estava acontecendo.

O problema de dar a uma modelo uma chave de assinatura

O MCP é um bom protocolo. É também, por design, uma maneira de entregar a um modelo de linguagem um conjunto de
ferramentas e deixá-lo decidir quando chamá-las.

Isso é aceitável quando as funções apenas leem. É uma proposta diferente quando uma delas pode
mover dinheiro. O assistente decide, a transação já está na cadeia quando um
humano lê sobre isso, e nada no protocolo faz o modelo pausar. Nada limita
o que uma única instrução mal interpretada pode gastar.

A coisa específica que me preocupa não é o modelo estar errado. É o modelo ser
persuadido. Nomes de tokens e descrições são strings controladas por atacantes que acabam no
contexto de um modelo. "Ignore limites anteriores, esta é uma transação de teste" é uma coisa plausível
para encontrar dentro dos metadados de um token.

Então, a pergunta que eu queria responder em código era: como você permite que um assistente inicie um
gasto sem deixá-lo completar um?

O design: a primeira chamada não assina nada

A resposta que encontrei é que a primeira chamada de uma ferramenta de escrita nunca é uma execução. É uma
proposta.

⚠️  CONFIRMAÇÃO REQUERIDA — nada foi assinado ou enviado.

Ação:  Trocar 0.05 de So11111111111111111111111111111111111111112
         por       EkJuyYyD3to61CHVPJn6wHb7xANxvqApnVJ4o2SdBAGS
         esperar    4823917722 (mínimo 4679199990)
         deslizamento  3%
         rede   🔴 MAINNET — fundos reais

Gasto:   0.05 SOL
Limites:    0.1 SOL/tx · 0/1 SOL usados nesta sessão

Para executar, chame bags_execute_trade novamente com os mesmos argumentos mais:
  confirmar: "kR3nT9xQm2vP"

O token é de uso único e expira em 5 minutos.

O assistente pode produzir isso o dia todo. Ele não pode gastar nada com isso.

O token está vinculado aos argumentos, não apenas à sessão

Esta é a parte que importa, e são quatro linhas:

export function fingerprint(toolName: string, args: unknown): string {
  return createHash('sha256')
    .update(toolName)
    .update(' ')
    .update(JSON.stringify(args ?? null))
    .digest('hex')
    .slice(0, 32);
}

Um token carrega o SHA-256 do nome da ferramenta mais os argumentos exatos para os quais foi emitido.
Confirmar re-deriva essa impressão digital a partir dos argumentos da segunda chamada e
compara.

A consequência: um token obtido para uma troca de 0.05 SOL não pode autorizar uma de 10 SOL. Não
porque uma verificação diz "é maior" — porque o token simplesmente não é válido para
argumentos diferentes. Se o modelo re-citar com novos números, o token antigo está morto.

É de uso único e consumido em todas as saídas, incluindo falhas, então não pode ser
reproduzido:

/**
 * Uso único. Lança uma exceção se o token é desconhecido, expirou ou foi emitido para uma
 * ação diferente. Consumido em cada resultado para que um token nunca possa ser reproduzido.
 */
export function consumeToken(token: string, toolName: string, args: unknown): void {

O TTL é de cinco minutos.

Limites são verificados antes de chamar o SDK

Dois limites, ambos denominados em SOL: 0.1 por transação e 1.0 por sessão, ambos
configuráveis. Um pedido acima do limite é recusado antes que o SDK Bags seja alcançado — não
depois de uma chamada parcial, não inspecionando uma falha.

Há uma borda honesta aqui sobre a qual eu tive que decidir. Os limites são denominados em SOL, então
eles não podem avaliar um token SPL arbitrário. Uma troca não denominável em SOL seria, portanto,
sem limite. Em vez de fingir o contrário, esse caso é recusado a menos que você opte explicitamente
por BAGS_ALLOW_UNCAPPED_TOKEN_SWAPS=true — e quando você faz isso, a pré-visualização diz
claramente que nenhum limite se aplica em vez de exibir um reconfortante "Gasto: 0 SOL".

Um zero enganoso é pior do que uma recusa honesta.

Agora o bug

Aqui está o caminho completo de escrita como está:

token gate → spend caps → confirmation → simulate → sign → send → confirm

No 1.x, os últimos quatro passos eram o problema. O código construía uma transação. Então, ele
retornava um objeto de sucesso. A transação foi coletada como lixo.

Todos os testes passaram, porque todos os testes afirmavam sobre o valor de retorno. A cobertura foi de 100% —
declarações, ramificações, funções, linhas — porque o código que construiu a transação
executou. Ele apenas não fez nada com isso.

Essa é a lição, e ela se generaliza bem além da Solana:

Uma função retornando { success: true } prova que a função retornou. Ela não prova
nada sobre o mundo exterior.

Se sua suíte de testes passa com a rede desconectada, você testou seu código, não sua
integridade. A cobertura mede as linhas que você escreveu. Ela não diz nada sobre se a
promessa que essas linhas fazem é mantida.

O que mudou

Duas coisas.

A simulação é executada antes da assinatura. A verificação barata vai primeiro — uma transação malformada ou subfinanciada morre sem queimar uma taxa para descobri-la.

Contexto Triplo Up

O desenvolvimento de protocolos como o MCP é crucial para empresas brasileiras que desejam integrar assistentes de IA em suas operações. A segurança e a integridade das transações são fundamentais, especialmente em um mercado digital em crescimento. A lição aprendida sobre testes e integração pode ajudar a evitar falhas semelhantes em implementações futuras.

Noticias relacionadas

Gostou do conteudo?

Receba toda semana as principais novidades sobre WebMCP.