Introdução
Por definições oficiais, o MCP (Model-Context Protocol) é um protocolo aberto e universal que padroniza a forma como aplicações de IA interagem com dados e serviços externos, a fim de alimentar os LLMs com contexto adicional.
Em resumo, é um protocolo que permite que aplicações ampliem o "conhecimento" de uma IA, por meio da disponibilização de ferramentas e dados adicionais em tempo real. Imagine poder perguntar a uma IA qualquer: "Quais são as rotas que mais gasto no Uber?" ou "Qual foi o valor total das minhas corridas no último mês?". Possivelmente esses dados são disponibilizados na própria API do Uber, e para tal seria necessário um desenvolvedor para extrair "manualmente" as informações integrando a API. A ideia do MCP é possibilitar que o próprio agente de IA adquira a capacidade de consumir a API e responder a essas perguntas.
"Pense no MCP como uma porta USB-C para aplicativos de IA. Assim como o USB-C fornece uma maneira padronizada de conectar seus dispositivos a diversos periféricos e acessórios. O MCP fornece uma maneira padronizada de conectar modelos de IA a diferentes fontes e ferramentas de dados". (Anthropic, 2024)
Antes de começarmos, é importante conhecer alguns dos conceitos básicos do protocolo:
Fonte Imagem
- Server: é o componente responsável por expor um contexto adicional, por exemplo, acesso a fonte de dados ou funcionalidade externa. Ele é responsável por executar as solicitações recebidas do agente de IA (clientes).
- Client: aplicações ou agentes de IA que utiliza o MCP Server para acessar ferramentas e recursos adicionais, expandindo suas capacidades.
- Tools: funcionalidades específicas fornecidas pelo MCP Server à IA.
Para mais informações sobre o protocolo, recomendo visitar a documentação oficial.
Neste artigo, vamos demonstrar como criar um MCP Server em Golang que utiliza a API pública do Cartola FC. Com ele, um agente de IA será capaz de responder perguntas sobre o Fantasy Game, como as pontuações de jogadores em rodadas atuais ou específicas.
O que a aplicação vai fazer?
Nosso objetivo é criar um MCP Server que consuma a API oficial do Cartola FC para permitir que um agente de IA responda a seguinte pergunta e suas variações:
"Qual a pontuação do jogador Fulano na rodada atual"?
A aplicação servidora vai expor Tools específicas que possibilitam a IA responder a esta pergunta, entretanto mais Tools podem ser construídas a fim de responder outras questões. Caso queira desenvolver outras tools, segue referência da api utilizada.
Implementação do MCP Server
MCP com Golang
Embora o MCP seja um protocolo genérico, até o momento não existe uma SDK oficial para Golang. No entanto, bibliotecas como metoro-io/mcp-golang e mark3labs/mcp-go oferecem implementações práticas. Para este artigo, escolhemos a mcp-golang por questões didáticas, mas qualquer uma das duas poderia ser utilizada.
Dito isso, vou mostrar como foi construído o Server para o Cartola FC:
package main
import (
"encoding/json"
"io"
"log"
"net/http"
"strconv"
mcp_golang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/mcp-golang/transport/stdio"
)
const (
API_URL = "https://api.cartolafc.globo.com"
)
type PlayerScoreDefaultInput struct{}
type DefaultResponse struct {
Content string `json:"content"`
}
type PlayerScoreInputByRound struct {
Round int `json:"round"`
}
func main() {
done := make(chan struct{})
// Criação da instância do Server
server := mcp_golang.NewServer(stdio.NewStdioServerTransport())
// Criação das tools específicas
err := server.RegisterTool("pontuacoes_jogadores",
"Retorna a pontuação parcial de todos os jogadores na rodada atual", handlePontuacoesJogadores)
if err != nil {
log.Fatalf("Erro ao registrar tool: %v", err)
}
err = server.RegisterTool("pontuacoes_jogadores_por_rodada",
"Retorna a pontuação de todos os jogadores na rodada informada", handlePontuacoesJogadoresPorRodada)
if err != nil {
log.Fatalf("Erro ao registrar tool: %v", err)
}
// Sobe o servidor
err = server.Serve()
if err != nil {
log.Fatalf("Erro ao iniciar servidor: %v", err)
}
<-done
}
Perceba que a função main é responsável por criar a instância do servidor MCP, registrar as Tools e executar o servidor.
Tools
pontuacoes_jogadores: Retorna a pontuação parcial de todos os jogadores na rodada atual.
pontuacoes_jogadores_por_rodada: Retorna a pontuação de todos os jogadores em uma rodada específica informada.
Esse é o ponto central do nosso MCP, é o trecho de código capaz de dar contexto adicional a IA e fazer com que seja possível responder as perguntas específicas sobre o Cartola FC. Perceba que esse contexto é definido explicitamente por nós. Caso quiséssemos que a IA fosse capaz de responder sobre outras questões, como por exemplo, a pontuação de um time, deveríamos criar uma tool específica para tal.
Por sua vez, cada tool precisa executar uma função, neste caso estamos o fazendo em handlePontuacoesJogadores e handlePontuacoesJogadoresPorRodada:
func handlePontuacoesJogadores(params *PlayerScoreDefaultInput) (*mcp_golang.ToolResponse, error) {
response, err := getPlayersScores()
if err != nil {
return nil, err
}
return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(response)), nil
}
func handlePontuacoesJogadoresPorRodada(params *PlayerScoreInputByRound) (*mcp_golang.ToolResponse, error) {
response, err := getPlayersScoresByRound(params.Round)
if err != nil {
return nil, err
}
return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(response)), nil
}
Basicamente para ambas as tools é realizado uma consulta na API do Cartola FC e retornado as informações, um deles utilizando o parâmetro da rodada e o outro não.
É válido mencionar que não é realizado nenhum tratamento em código para o retorno do endpoint, o que acaba implicando que o cliente tenha acesso apenas aos dados de maneira "crua", assim como retornado pela API oficial.
Se fosse o caso, poderíamos ter feito tratamentos no nosso código para por exemplo buscar pelo nome do jogador e assim "otimizar" o trabalho realizado pelo LLM, já retornando a informação.
func getPlayersScores() (string, error) {
url := API_URL + "/atletas/pontuados"
resp, err := http.Get(url)
if err != nil {
log.Printf("Erro ao fazer requisição para API: %v", err)
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Printf("Erro ao ler resposta da API: %v", err)
return "", err
}
response := &DefaultResponse{
Content: string(body),
}
jsonResponse, err := json.Marshal(response)
if err != nil {
log.Printf("Erro ao converter resposta para JSON: %v", err)
return "", err
}
return string(jsonResponse), nil
}
func getPlayersScoresByRound(round int) (string, error) {
url := API_URL + "/atletas/pontuados/" + strconv.Itoa(round)
resp, err := http.Get(url)
if err != nil {
log.Printf("Erro ao fazer requisição para API: %v", err)
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Printf("Erro ao ler resposta da API: %v", err)
return "", err
}
response := &DefaultResponse{
Content: string(body),
}
jsonResponse, err := json.Marshal(response)
if err != nil {
log.Printf("Erro ao converter resposta para JSON: %v", err)
return "", err
}
return string(jsonResponse), nil
}
Resultados
Agora é a hora da verdade. Farei uma comparação da interação do antes e depois com um agente de IA (para tal utilizei o Cursor AI) para verificar se o MCP Server construído foi efetivo ou não.
Antes
Depois
Percebe-se que sem a conexão com o MCP Server, a IA procura por contextos externos (acesso a internet) para responder a pergunta solicitada, entretanto mesmo sugerindo a requisição a API, acaba não sendo efetiva na sua resposta.
Por sua vez, com o MCP Server disponibilizando o contexto correto, a IA desenvolve a capacidade de executar as tools específicas e assim responder as perguntas mencionadas, com velocidade e assertividade.
Conclusão
Apesar de ser um exemplo didático, a aplicação serviu como uma boa prova de conceito para demonstrar o potencial que se espera de uma IA utilizando o protocolo MCP. Pense nisso no âmbito da integração de grandes sistemas, no consumo de grandes fontes de dados e consequentemente na capacidade do próprio agente de IA consumir informações em tempo real para adquirir mais contexto da situação. Em suma, o MCP vem com o objetivo fundamental de simplificar como os agentes de IA interagem com dados externos.
Código produzido também no Github
Referências
Model Context Protocol - Anthropic
Model Context Protocol (MCP) Para Sistemas de IA Generativa – Conceito, Aplicações e Desafios
Criando um MCP Server usando Go - Elton Minetto
Código Fonte TV
Top comments (3)
Que artigo legal! Parabéns pela ideia.
Muito obrigado! Feliz que tenha gostado :)
Ótimo artigo Arthur 👏👏👏