Pular para o conteúdo
astorlm
Idioma: Português
← Mapa

Nível 10

MCP

Até agora cada ferramenta era uma função que você escrevia dentro do seu próprio agente. O MCP é um plugue padrão: qualquer programa pode oferecer ferramentas por ele, e qualquer agente pode usá-las.
1/19 Dobras do bandoneón:
  • user
  • assistant
  • tool_result
Dream Land. Dois servidores MCP esperam diante de suas portas: weather e maps, cada um um programa à parte. Kirby é o cliente MCP dentro do agente, e serve para qualquer servidor com a mesma boca.

EventBus

O problema

Cada serviço que seu agente deveria alcançar (uma agenda, um repositório, um banco de dados, um navegador) significa escrever uma ferramenta à mão: o esquema, o código, o tratamento de erros. Depois o próximo agente, ou o próximo app, escreve a mesma ferramenta de novo. E quando o serviço muda, cada cópia quebra por conta própria.

A solução

O Model Context Protocol (MCP) separa os dois lados. Um servidor MCP é um programa que oferece ferramentas; quem constrói o serviço o escreve uma vez. Um cliente MCP vive dentro do agente e fala o protocolo. Eles podem rodar na mesma máquina, com o servidor como processo filho falando por stdin e stdout, ou longe, por HTTP. A conversa sempre tem os mesmos três passos:

  • initialize

    O aperto de mão: cliente e servidor dizem quem são e que versão do protocolo falam.

  • tools/list

    O servidor descreve suas ferramentas: nome, descrição e esquema de entrada, as mesmas três coisas do nível 3.

  • tools/call

    Cada vez que o modelo pede uma delas, o cliente manda o nome e os argumentos, e recebe o resultado.

As ferramentas que você recebe são ferramentas comuns. Entram na lista que vai com cada requisição, o loop as roda como qualquer outra e o modelo não tem como saber de onde vieram. E como o plugue é padrão, o mesmo servidor funciona no Claude Code, no Codex, no Cursor, no VS Code ou no seu próprio agente.

O elenco

O mesmo elenco de sempre, em Dream Land, com um amigo novo.

Kirby o cliente MCP
Parte do seu agente. Uma boca que serve para qualquer servidor, e copia o que cada um sabe fazer.
Os inimigos servidores MCP
Programas à parte, cada um na sua porta. Voltam para lá depois que Kirby os copia: continuam rodando.
As habilidades tools/list
PARASOL e WHEEL: as ferramentas que cada servidor descreveu, agora na barra de status que o modelo lê.
Os cabos o protocolo
O mesmo tipo de plugue para todos os servidores. Um tools/call desce por um e o resultado volta.
Astor o loop
Roda o loop como sempre, e entrega cada chamada MCP ao Kirby.
O Oráculo o modelo
Escolhe na caixa de ferramentas pelo nome e pela descrição, seja MCP ou não.

O código

Com astorlm: mountMcpServer() se conecta, lista as ferramentas e as adapta, com o nome <servidor>__<ferramenta> para que dois servidores não colidam. Suas tools entram no agente como qualquer outra, e close() desliga.

Do zero: um cliente stdio é um processo filho e JSON-RPC, um objeto JSON por linha: o aperto de mão, tools/list e uma função por ferramenta que manda tools/call. Depois as ferramentas entram no loop do nível 2.

import { OpenAIProvider, createLocalAgent, mountMcpServer } from 'astorlm'

// 1. Mount each MCP server: connect, ask for its tools (tools/list), adapt them.
//    Each one is a separate program; nobody wrote its schemas in your code.
const weather = await mountMcpServer({
  name: 'weather', // becomes the prefix: weather__forecast, weather__alerts
  transport: { type: 'stdio', command: 'npx', args: ['-y', 'dreamland-weather-mcp'] }, // runs it as a child process
})

const maps = await mountMcpServer({
  name: 'maps',
  transport: { type: 'http', url: 'https://maps.dreamland.example/mcp' }, // or a server that's already running
})

const agent = await createLocalAgent({
  // Any OpenAI-compatible endpoint: OpenAI, Ollama, LM Studio, vLLM, a proxy…
  provider: new OpenAIProvider({
    baseURL: 'http://localhost:11434/v1', // e.g. Ollama's default address
    model: 'your-model', // e.g. 'llama3.1', 'gpt-4o-mini'
    apiKey: 'YOUR_API_KEY', // local servers usually ignore it
  }),
  // 2. MCP tools are tools: mix them with your own, or keep only the ones you need.
  tools: [...weather.tools, ...maps.tools],
  maxTurns: 10,
})

agent.on('tool-start', ({ name }) => console.log('→', name)) // maps__route, then weather__forecast

try {
  await agent.run('Picnic at the Fountain of Dreams tomorrow. How do I get there from Cappy Town, and will it rain?')
} finally {
  // 3. Hang up when you're done: a stdio server is a process of yours.
  await Promise.all([weather.close(), maps.close()])
}

O que observar

  • Cada ferramenta viaja em cada requisição. Um servidor com quarenta ferramentas soma quarenta esquemas a cada turno, e uma lista longa torna mais difícil escolher a certa. Monte só os servidores de que precisa, e passe só as ferramentas que usa: weather.tools.filter(…).
  • Um servidor é código que você roda. Um servidor stdio roda com as suas permissões, na sua máquina. Trate-o como uma dependência: instale de uma fonte confiável e fixe a versão.
  • Descrições também são instruções. O modelo lê cada descrição de ferramenta como se você a tivesse escrito, e cada resultado como dados que podem trazer ordens. Um servidor que você não controla pode dirigir seu agente por qualquer um dos dois caminhos (nível 18).
  • Servidores remotos precisam de credenciais. Por HTTP, passe um token nos headers, limitado ao que o agente precisa, nunca a sua chave todo-poderosa.
  • Feche o que abrir. Um servidor stdio vive enquanto dura a conexão. Feche quando o agente terminar, ou ele continua rodando em segundo plano.